diff options
author | monster <monster@ydb.tech> | 2022-07-07 14:41:37 +0300 |
---|---|---|
committer | monster <monster@ydb.tech> | 2022-07-07 14:41:37 +0300 |
commit | 06e5c21a835c0e923506c4ff27929f34e00761c2 (patch) | |
tree | 75efcbc6854ef9bd476eb8bf00cc5c900da436a2 /contrib/python/ipython/py3/IPython | |
parent | 03f024c4412e3aa613bb543cf1660176320ba8f4 (diff) | |
download | ydb-06e5c21a835c0e923506c4ff27929f34e00761c2.tar.gz |
fix ya.make
Diffstat (limited to 'contrib/python/ipython/py3/IPython')
177 files changed, 0 insertions, 49717 deletions
diff --git a/contrib/python/ipython/py3/IPython/__init__.py b/contrib/python/ipython/py3/IPython/__init__.py deleted file mode 100644 index 7ebb80b362..0000000000 --- a/contrib/python/ipython/py3/IPython/__init__.py +++ /dev/null @@ -1,156 +0,0 @@ -""" -IPython: tools for interactive and parallel computing in Python. - -https://ipython.org -""" -#----------------------------------------------------------------------------- -# Copyright (c) 2008-2011, IPython Development Team. -# Copyright (c) 2001-2007, Fernando Perez <fernando.perez@colorado.edu> -# Copyright (c) 2001, Janko Hauser <jhauser@zscout.de> -# Copyright (c) 2001, Nathaniel Gray <n8gray@caltech.edu> -# -# Distributed under the terms of the Modified BSD License. -# -# The full license is in the file COPYING.txt, distributed with this software. -#----------------------------------------------------------------------------- - -#----------------------------------------------------------------------------- -# Imports -#----------------------------------------------------------------------------- - -import os -import sys - -#----------------------------------------------------------------------------- -# Setup everything -#----------------------------------------------------------------------------- - -# Don't forget to also update setup.py when this changes! -if sys.version_info < (3, 8): - raise ImportError( - """ -IPython 8+ supports Python 3.8 and above, following NEP 29. -When using Python 2.7, please install IPython 5.x LTS Long Term Support version. -Python 3.3 and 3.4 were supported up to IPython 6.x. -Python 3.5 was supported with IPython 7.0 to 7.9. -Python 3.6 was supported with IPython up to 7.16. -Python 3.7 was still supported with the 7.x branch. - -See IPython `README.rst` file for more information: - - https://github.com/ipython/ipython/blob/master/README.rst - -""" - ) - -#----------------------------------------------------------------------------- -# Setup the top level names -#----------------------------------------------------------------------------- - -from .core.getipython import get_ipython -from .core import release -from .core.application import Application -from .terminal.embed import embed - -from .core.interactiveshell import InteractiveShell -from .utils.sysinfo import sys_info -from .utils.frame import extract_module_locals - -# Release data -__author__ = '%s <%s>' % (release.author, release.author_email) -__license__ = release.license -__version__ = release.version -version_info = release.version_info -# list of CVEs that should have been patched in this release. -# this is informational and should not be relied upon. -__patched_cves__ = {"CVE-2022-21699"} - - -def embed_kernel(module=None, local_ns=None, **kwargs): - """Embed and start an IPython kernel in a given scope. - - If you don't want the kernel to initialize the namespace - from the scope of the surrounding function, - and/or you want to load full IPython configuration, - you probably want `IPython.start_kernel()` instead. - - Parameters - ---------- - module : types.ModuleType, optional - The module to load into IPython globals (default: caller) - local_ns : dict, optional - The namespace to load into IPython user namespace (default: caller) - **kwargs : various, optional - Further keyword args are relayed to the IPKernelApp constructor, - allowing configuration of the Kernel. Will only have an effect - on the first embed_kernel call for a given process. - """ - - (caller_module, caller_locals) = extract_module_locals(1) - if module is None: - module = caller_module - if local_ns is None: - local_ns = caller_locals - - # Only import .zmq when we really need it - from ipykernel.embed import embed_kernel as real_embed_kernel - real_embed_kernel(module=module, local_ns=local_ns, **kwargs) - -def start_ipython(argv=None, **kwargs): - """Launch a normal IPython instance (as opposed to embedded) - - `IPython.embed()` puts a shell in a particular calling scope, - such as a function or method for debugging purposes, - which is often not desirable. - - `start_ipython()` does full, regular IPython initialization, - including loading startup files, configuration, etc. - much of which is skipped by `embed()`. - - This is a public API method, and will survive implementation changes. - - Parameters - ---------- - argv : list or None, optional - If unspecified or None, IPython will parse command-line options from sys.argv. - To prevent any command-line parsing, pass an empty list: `argv=[]`. - user_ns : dict, optional - specify this dictionary to initialize the IPython user namespace with particular values. - **kwargs : various, optional - Any other kwargs will be passed to the Application constructor, - such as `config`. - """ - from IPython.terminal.ipapp import launch_new_instance - return launch_new_instance(argv=argv, **kwargs) - -def start_kernel(argv=None, **kwargs): - """Launch a normal IPython kernel instance (as opposed to embedded) - - `IPython.embed_kernel()` puts a shell in a particular calling scope, - such as a function or method for debugging purposes, - which is often not desirable. - - `start_kernel()` does full, regular IPython initialization, - including loading startup files, configuration, etc. - much of which is skipped by `embed()`. - - Parameters - ---------- - argv : list or None, optional - If unspecified or None, IPython will parse command-line options from sys.argv. - To prevent any command-line parsing, pass an empty list: `argv=[]`. - user_ns : dict, optional - specify this dictionary to initialize the IPython user namespace with particular values. - **kwargs : various, optional - Any other kwargs will be passed to the Application constructor, - such as `config`. - """ - import warnings - - warnings.warn( - "start_kernel is deprecated since IPython 8.0, use from `ipykernel.kernelapp.launch_new_instance`", - DeprecationWarning, - stacklevel=2, - ) - from ipykernel.kernelapp import launch_new_instance - return launch_new_instance(argv=argv, **kwargs) diff --git a/contrib/python/ipython/py3/IPython/__main__.py b/contrib/python/ipython/py3/IPython/__main__.py deleted file mode 100644 index d5123f33a2..0000000000 --- a/contrib/python/ipython/py3/IPython/__main__.py +++ /dev/null @@ -1,14 +0,0 @@ -# encoding: utf-8 -"""Terminal-based IPython entry point. -""" -#----------------------------------------------------------------------------- -# Copyright (c) 2012, IPython Development Team. -# -# Distributed under the terms of the Modified BSD License. -# -# The full license is in the file COPYING.txt, distributed with this software. -#----------------------------------------------------------------------------- - -from IPython import start_ipython - -start_ipython() diff --git a/contrib/python/ipython/py3/IPython/consoleapp.py b/contrib/python/ipython/py3/IPython/consoleapp.py deleted file mode 100644 index c2bbe1888f..0000000000 --- a/contrib/python/ipython/py3/IPython/consoleapp.py +++ /dev/null @@ -1,12 +0,0 @@ -""" -Shim to maintain backwards compatibility with old IPython.consoleapp imports. -""" -# Copyright (c) IPython Development Team. -# Distributed under the terms of the Modified BSD License. - -from warnings import warn - -warn("The `IPython.consoleapp` package has been deprecated since IPython 4.0." - "You should import from jupyter_client.consoleapp instead.", stacklevel=2) - -from jupyter_client.consoleapp import * diff --git a/contrib/python/ipython/py3/IPython/core/__init__.py b/contrib/python/ipython/py3/IPython/core/__init__.py deleted file mode 100644 index e69de29bb2..0000000000 --- a/contrib/python/ipython/py3/IPython/core/__init__.py +++ /dev/null diff --git a/contrib/python/ipython/py3/IPython/core/alias.py b/contrib/python/ipython/py3/IPython/core/alias.py deleted file mode 100644 index 2ad990231a..0000000000 --- a/contrib/python/ipython/py3/IPython/core/alias.py +++ /dev/null @@ -1,258 +0,0 @@ -# encoding: utf-8 -""" -System command aliases. - -Authors: - -* Fernando Perez -* Brian Granger -""" - -#----------------------------------------------------------------------------- -# Copyright (C) 2008-2011 The IPython Development Team -# -# Distributed under the terms of the BSD License. -# -# The full license is in the file COPYING.txt, distributed with this software. -#----------------------------------------------------------------------------- - -#----------------------------------------------------------------------------- -# Imports -#----------------------------------------------------------------------------- - -import os -import re -import sys - -from traitlets.config.configurable import Configurable -from .error import UsageError - -from traitlets import List, Instance -from logging import error - -#----------------------------------------------------------------------------- -# Utilities -#----------------------------------------------------------------------------- - -# This is used as the pattern for calls to split_user_input. -shell_line_split = re.compile(r'^(\s*)()(\S+)(.*$)') - -def default_aliases(): - """Return list of shell aliases to auto-define. - """ - # Note: the aliases defined here should be safe to use on a kernel - # regardless of what frontend it is attached to. Frontends that use a - # kernel in-process can define additional aliases that will only work in - # their case. For example, things like 'less' or 'clear' that manipulate - # the terminal should NOT be declared here, as they will only work if the - # kernel is running inside a true terminal, and not over the network. - - if os.name == 'posix': - default_aliases = [('mkdir', 'mkdir'), ('rmdir', 'rmdir'), - ('mv', 'mv'), ('rm', 'rm'), ('cp', 'cp'), - ('cat', 'cat'), - ] - # Useful set of ls aliases. The GNU and BSD options are a little - # different, so we make aliases that provide as similar as possible - # behavior in ipython, by passing the right flags for each platform - if sys.platform.startswith('linux'): - ls_aliases = [('ls', 'ls -F --color'), - # long ls - ('ll', 'ls -F -o --color'), - # ls normal files only - ('lf', 'ls -F -o --color %l | grep ^-'), - # ls symbolic links - ('lk', 'ls -F -o --color %l | grep ^l'), - # directories or links to directories, - ('ldir', 'ls -F -o --color %l | grep /$'), - # things which are executable - ('lx', 'ls -F -o --color %l | grep ^-..x'), - ] - elif sys.platform.startswith('openbsd') or sys.platform.startswith('netbsd'): - # OpenBSD, NetBSD. The ls implementation on these platforms do not support - # the -G switch and lack the ability to use colorized output. - ls_aliases = [('ls', 'ls -F'), - # long ls - ('ll', 'ls -F -l'), - # ls normal files only - ('lf', 'ls -F -l %l | grep ^-'), - # ls symbolic links - ('lk', 'ls -F -l %l | grep ^l'), - # directories or links to directories, - ('ldir', 'ls -F -l %l | grep /$'), - # things which are executable - ('lx', 'ls -F -l %l | grep ^-..x'), - ] - else: - # BSD, OSX, etc. - ls_aliases = [('ls', 'ls -F -G'), - # long ls - ('ll', 'ls -F -l -G'), - # ls normal files only - ('lf', 'ls -F -l -G %l | grep ^-'), - # ls symbolic links - ('lk', 'ls -F -l -G %l | grep ^l'), - # directories or links to directories, - ('ldir', 'ls -F -G -l %l | grep /$'), - # things which are executable - ('lx', 'ls -F -l -G %l | grep ^-..x'), - ] - default_aliases = default_aliases + ls_aliases - elif os.name in ['nt', 'dos']: - default_aliases = [('ls', 'dir /on'), - ('ddir', 'dir /ad /on'), ('ldir', 'dir /ad /on'), - ('mkdir', 'mkdir'), ('rmdir', 'rmdir'), - ('echo', 'echo'), ('ren', 'ren'), ('copy', 'copy'), - ] - else: - default_aliases = [] - - return default_aliases - - -class AliasError(Exception): - pass - - -class InvalidAliasError(AliasError): - pass - -class Alias(object): - """Callable object storing the details of one alias. - - Instances are registered as magic functions to allow use of aliases. - """ - - # Prepare blacklist - blacklist = {'cd','popd','pushd','dhist','alias','unalias'} - - def __init__(self, shell, name, cmd): - self.shell = shell - self.name = name - self.cmd = cmd - self.__doc__ = "Alias for `!{}`".format(cmd) - self.nargs = self.validate() - - def validate(self): - """Validate the alias, and return the number of arguments.""" - if self.name in self.blacklist: - raise InvalidAliasError("The name %s can't be aliased " - "because it is a keyword or builtin." % self.name) - try: - caller = self.shell.magics_manager.magics['line'][self.name] - except KeyError: - pass - else: - if not isinstance(caller, Alias): - raise InvalidAliasError("The name %s can't be aliased " - "because it is another magic command." % self.name) - - if not (isinstance(self.cmd, str)): - raise InvalidAliasError("An alias command must be a string, " - "got: %r" % self.cmd) - - nargs = self.cmd.count('%s') - self.cmd.count('%%s') - - if (nargs > 0) and (self.cmd.find('%l') >= 0): - raise InvalidAliasError('The %s and %l specifiers are mutually ' - 'exclusive in alias definitions.') - - return nargs - - def __repr__(self): - return "<alias {} for {!r}>".format(self.name, self.cmd) - - def __call__(self, rest=''): - cmd = self.cmd - nargs = self.nargs - # Expand the %l special to be the user's input line - if cmd.find('%l') >= 0: - cmd = cmd.replace('%l', rest) - rest = '' - - if nargs==0: - if cmd.find('%%s') >= 1: - cmd = cmd.replace('%%s', '%s') - # Simple, argument-less aliases - cmd = '%s %s' % (cmd, rest) - else: - # Handle aliases with positional arguments - args = rest.split(None, nargs) - if len(args) < nargs: - raise UsageError('Alias <%s> requires %s arguments, %s given.' % - (self.name, nargs, len(args))) - cmd = '%s %s' % (cmd % tuple(args[:nargs]),' '.join(args[nargs:])) - - self.shell.system(cmd) - -#----------------------------------------------------------------------------- -# Main AliasManager class -#----------------------------------------------------------------------------- - -class AliasManager(Configurable): - - 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): - super(AliasManager, self).__init__(shell=shell, **kwargs) - # For convenient access - self.linemagics = self.shell.magics_manager.magics['line'] - self.init_aliases() - - def init_aliases(self): - # Load default & user aliases - for name, cmd in self.default_aliases + self.user_aliases: - if cmd.startswith('ls ') and self.shell.colors == 'NoColor': - cmd = cmd.replace(' --color', '') - self.soft_define_alias(name, cmd) - - @property - def aliases(self): - return [(n, func.cmd) for (n, func) in self.linemagics.items() - if isinstance(func, Alias)] - - def soft_define_alias(self, name, cmd): - """Define an alias, but don't raise on an AliasError.""" - try: - self.define_alias(name, cmd) - except AliasError as e: - error("Invalid alias: %s" % e) - - def define_alias(self, name, cmd): - """Define a new alias after validating it. - - This will raise an :exc:`AliasError` if there are validation - problems. - """ - caller = Alias(shell=self.shell, name=name, cmd=cmd) - self.shell.magics_manager.register_function(caller, magic_kind='line', - magic_name=name) - - def get_alias(self, name): - """Return an alias, or None if no alias by that name exists.""" - aname = self.linemagics.get(name, None) - return aname if isinstance(aname, Alias) else None - - def is_alias(self, name): - """Return whether or not a given name has been defined as an alias""" - return self.get_alias(name) is not None - - def undefine_alias(self, name): - if self.is_alias(name): - del self.linemagics[name] - else: - raise ValueError('%s is not an alias' % name) - - def clear_aliases(self): - for name, cmd in self.aliases: - self.undefine_alias(name) - - def retrieve_alias(self, name): - """Retrieve the command to which an alias expands.""" - caller = self.get_alias(name) - if caller: - return caller.cmd - else: - raise ValueError('%s is not an alias' % name) diff --git a/contrib/python/ipython/py3/IPython/core/application.py b/contrib/python/ipython/py3/IPython/core/application.py deleted file mode 100644 index 0cdea5c69b..0000000000 --- a/contrib/python/ipython/py3/IPython/core/application.py +++ /dev/null @@ -1,490 +0,0 @@ -# encoding: utf-8 -""" -An application for IPython. - -All top-level applications should use the classes in this module for -handling configuration and creating configurables. - -The job of an :class:`Application` is to create the master configuration -object and then create the configurable objects, passing the config to them. -""" - -# Copyright (c) IPython Development Team. -# Distributed under the terms of the Modified BSD License. - -import atexit -from copy import deepcopy -import glob -import logging -import os -import shutil -import sys - -from pathlib import Path - -from traitlets.config.application import Application, catch_config_error -from traitlets.config.loader import ConfigFileNotFound, PyFileConfigLoader -from IPython.core import release, crashhandler -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 traitlets import ( - List, Unicode, Type, Bool, Set, Instance, Undefined, - default, observe, -) - -if os.name == "nt": - programdata = os.environ.get("PROGRAMDATA", None) - if programdata is not None: - SYSTEM_CONFIG_DIRS = [str(Path(programdata) / "ipython")] - else: # PROGRAMDATA is not defined by default on XP. - SYSTEM_CONFIG_DIRS = [] -else: - SYSTEM_CONFIG_DIRS = [ - "/usr/local/etc/ipython", - "/etc/ipython", - ] - - -ENV_CONFIG_DIRS = [] -_env_config_dir = os.path.join(sys.prefix, 'etc', 'ipython') -if _env_config_dir not in SYSTEM_CONFIG_DIRS: - # only add ENV_CONFIG if sys.prefix is not already included - 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 ) - -# aliases and flags - -base_aliases = {} -if isinstance(Application.aliases, dict): - # traitlets 5 - base_aliases.update(Application.aliases) -base_aliases.update( - { - "profile-dir": "ProfileDir.location", - "profile": "BaseIPythonApplication.profile", - "ipython-dir": "BaseIPythonApplication.ipython_dir", - "log-level": "Application.log_level", - "config": "BaseIPythonApplication.extra_config_file", - } -) - -base_flags = dict() -if isinstance(Application.flags, dict): - # traitlets 5 - base_flags.update(Application.flags) -base_flags.update( - dict( - debug=( - {"Application": {"log_level": logging.DEBUG}}, - "set log level to logging.DEBUG (maximize logging output)", - ), - quiet=( - {"Application": {"log_level": logging.CRITICAL}}, - "set log level to logging.CRITICAL (minimize logging output)", - ), - init=( - { - "BaseIPythonApplication": { - "copy_config_files": True, - "auto_create": True, - } - }, - """Initialize profile with default config files. This is equivalent - to running `ipython profile create <profile>` prior to startup. - """, - ), - ) -) - - -class ProfileAwareConfigLoader(PyFileConfigLoader): - """A Python file config loader that is aware of IPython profiles.""" - def load_subconfig(self, fname, path=None, profile=None): - if profile is not None: - try: - profile_dir = ProfileDir.find_profile_dir_by_name( - get_ipython_dir(), - profile, - ) - except ProfileDirError: - return - path = profile_dir.location - return super(ProfileAwareConfigLoader, self).load_subconfig(fname, path=path) - -class BaseIPythonApplication(Application): - - name = u'ipython' - description = Unicode(u'IPython: an enhanced interactive Python shell.') - version = Unicode(release.version) - - aliases = base_aliases - flags = base_flags - classes = List([ProfileDir]) - - # enable `load_subconfig('cfg.py', profile='name')` - python_config_loader_class = ProfileAwareConfigLoader - - # Track whether the config_file has changed, - # because some logic happens only if we aren't using the default. - config_file_specified = Set() - - config_file_name = Unicode() - @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']) - - # The directory that contains IPython's builtin profiles. - builtin_profile_dir = Unicode( - os.path.join(get_ipython_package_dir(), u'config', u'profile', u'default') - ) - - config_file_paths = List(Unicode()) - @default('config_file_paths') - def _config_file_paths_default(self): - return [] - - 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'] - try: - self.config_files.remove(old) - except ValueError: - pass - self.config_file_specified.add(new) - self.config_files.append(new) - - profile = Unicode(u'default', - help="""The IPython profile to use.""" - ).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'] - ) - - add_ipython_dir_to_sys_path = Bool( - False, - """Should the IPython profile directory be added to sys path ? - - This option was non-existing before IPython 8.0, and ipython_dir was added to - sys path to allow import of extensions present there. This was historical - baggage from when pip did not exist. This now default to false, - but can be set to true for legacy reasons. - """, - ).tag(config=True) - - 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') - def _ipython_dir_default(self): - d = get_ipython_dir() - 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') - def _profile_dir_default(self): - # avoid recursion - if self._in_init_profile_dir: - return - # profile_dir requested early, force initialization - 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) - - config_files = List(Unicode()) - @default('config_files') - def _config_files_default(self): - return [self.config_file_name] - - 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) - - 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) - - # The class to use as the crash handler. - crash_handler_class = Type(crashhandler.CrashHandler) - - @catch_config_error - def __init__(self, **kwargs): - super(BaseIPythonApplication, self).__init__(**kwargs) - # ensure current working directory exists - try: - os.getcwd() - except: - # exit if cwd doesn't exist - self.log.error("Current working directory doesn't exist.") - self.exit(1) - - #------------------------------------------------------------------------- - # Various stages of Application creation - #------------------------------------------------------------------------- - - def init_crash_handler(self): - """Create a crash handler, typically setting sys.excepthook to it.""" - self.crash_handler = self.crash_handler_class(self) - sys.excepthook = self.excepthook - def unset_crashhandler(): - sys.excepthook = sys.__excepthook__ - atexit.register(unset_crashhandler) - - def excepthook(self, etype, evalue, tb): - """this is sys.excepthook after init_crashhandler - - set self.verbose_crash=True to use our full crashhandler, instead of - a regular traceback with a short message (crash_handler_lite) - """ - - if self.verbose_crash: - 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'] - if old is not Undefined: - str_old = os.path.abspath(old) - if str_old in sys.path: - sys.path.remove(str_old) - if self.add_ipython_dir_to_sys_path: - str_path = os.path.abspath(new) - sys.path.append(str_path) - ensure_dir_exists(new) - readme = os.path.join(new, "README") - readme_src = os.path.join( - get_ipython_package_dir(), "config", "profile", "README" - ) - if not os.path.exists(readme) and os.path.exists(readme_src): - shutil.copy(readme_src, readme) - for d in ("extensions", "nbextensions"): - path = os.path.join(new, d) - try: - ensure_dir_exists(path) - except OSError as e: - # this will not be EEXIST - 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): - """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. - - `suppress_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; - Application.load_config_file( - self, - base_config, - path=self.config_file_paths - ) - except ConfigFileNotFound: - # 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 - - for config_file_name in self.config_files: - if not config_file_name or config_file_name == base_config: - continue - self.log.debug("Attempting to load config file: %s" % - self.config_file_name) - try: - Application.load_config_file( - self, - config_file_name, - path=self.config_file_paths - ) - except ConfigFileNotFound: - # Only warn if the default config file was NOT being used. - if config_file_name in self.config_file_specified: - msg = self.log.warning - else: - msg = self.log.debug - msg("Config file not found, skipping: %s", config_file_name) - except Exception: - # For testing purposes. - if not suppress_errors: - raise - self.log.warning("Error loading config file: %s" % - self.config_file_name, exc_info=True) - - def init_profile_dir(self): - """initialize the profile dir""" - self._in_init_profile_dir = True - if self.profile_dir is not None: - # already ran - return - if 'ProfileDir.location' not in self.config: - # location not specified, find by profile name - try: - p = ProfileDir.find_profile_dir_by_name(self.ipython_dir, self.profile, self.config) - except ProfileDirError: - # not found, maybe create it (always create default profile) - if self.auto_create or self.profile == 'default': - try: - p = ProfileDir.create_profile_dir_by_name(self.ipython_dir, self.profile, self.config) - except ProfileDirError: - self.log.fatal("Could not create profile: %r"%self.profile) - self.exit(1) - else: - self.log.info("Created profile dir: %r"%p.location) - else: - self.log.fatal("Profile %r not found."%self.profile) - self.exit(1) - else: - self.log.debug(f"Using existing profile dir: {p.location!r}") - else: - location = self.config.ProfileDir.location - # location is fully specified - try: - p = ProfileDir.find_profile_dir(location, self.config) - except ProfileDirError: - # not found, maybe create it - if self.auto_create: - try: - p = ProfileDir.create_profile_dir(location, self.config) - except ProfileDirError: - self.log.fatal("Could not create profile directory: %r"%location) - self.exit(1) - else: - self.log.debug("Creating new profile dir: %r"%location) - else: - self.log.fatal("Profile directory %r not found."%location) - self.exit(1) - else: - self.log.debug(f"Using existing profile dir: {p.location!r}") - # if profile_dir is specified explicitly, set profile name - dir_name = os.path.basename(p.location) - if dir_name.startswith('profile_'): - self.profile = dir_name[8:] - - self.profile_dir = p - self.config_file_paths.append(p.location) - self._in_init_profile_dir = False - - def init_config_files(self): - """[optionally] copy default config files into profile dir.""" - self.config_file_paths.extend(ENV_CONFIG_DIRS) - self.config_file_paths.extend(SYSTEM_CONFIG_DIRS) - # copy config files - path = Path(self.builtin_profile_dir) - if self.copy_config_files: - src = self.profile - - cfg = self.config_file_name - if path and (path / cfg).exists(): - self.log.warning( - "Staging %r from %s into %r [overwrite=%s]" - % (cfg, src, self.profile_dir.location, self.overwrite) - ) - self.profile_dir.copy_config_file(cfg, path=path, overwrite=self.overwrite) - else: - self.stage_default_config_file() - else: - # Still stage *bundled* config files, but not generated ones - # This is necessary for `ipython profile=sympy` to load the profile - # on the first go - files = path.glob("*.py") - for fullpath in files: - cfg = fullpath.name - if self.profile_dir.copy_config_file(cfg, path=path, overwrite=False): - # file was copied - self.log.warning("Staging bundled %s from %s into %r"%( - cfg, self.profile, self.profile_dir.location) - ) - - - def stage_default_config_file(self): - """auto generate default config file, and stage it into the profile.""" - s = self.generate_config_file() - config_file = Path(self.profile_dir.location) / self.config_file_name - if self.overwrite or not config_file.exists(): - self.log.warning("Generating default config file: %r" % (config_file)) - config_file.write_text(s, encoding="utf-8") - - @catch_config_error - def initialize(self, argv=None): - # don't hook up crash handler before parsing command-line - self.parse_command_line(argv) - self.init_crash_handler() - 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) - self.init_profile_dir() - self.init_config_files() - self.load_config_file() - # enforce cl-opts override configfile opts: - self.update_config(cl_config) diff --git a/contrib/python/ipython/py3/IPython/core/async_helpers.py b/contrib/python/ipython/py3/IPython/core/async_helpers.py deleted file mode 100644 index 0e7db0bb54..0000000000 --- a/contrib/python/ipython/py3/IPython/core/async_helpers.py +++ /dev/null @@ -1,156 +0,0 @@ -""" -Async helper function that are invalid syntax on Python 3.5 and below. - -This code is best effort, and may have edge cases not behaving as expected. In -particular it contain a number of heuristics to detect whether code is -effectively async and need to run in an event loop or not. - -Some constructs (like top-level `return`, or `yield`) are taken care of -explicitly to actually raise a SyntaxError and stay as close as possible to -Python semantics. -""" - - -import ast -import asyncio -import inspect -from functools import wraps - -_asyncio_event_loop = None - - -def get_asyncio_loop(): - """asyncio has deprecated get_event_loop - - Replicate it here, with our desired semantics: - - - always returns a valid, not-closed loop - - not thread-local like asyncio's, - because we only want one loop for IPython - - if called from inside a coroutine (e.g. in ipykernel), - return the running loop - - .. versionadded:: 8.0 - """ - try: - return asyncio.get_running_loop() - except RuntimeError: - # not inside a coroutine, - # track our own global - pass - - # not thread-local like asyncio's, - # because we only track one event loop to run for IPython itself, - # always in the main thread. - global _asyncio_event_loop - if _asyncio_event_loop is None or _asyncio_event_loop.is_closed(): - _asyncio_event_loop = asyncio.new_event_loop() - return _asyncio_event_loop - - -class _AsyncIORunner: - def __call__(self, coro): - """ - Handler for asyncio autoawait - """ - return get_asyncio_loop().run_until_complete(coro) - - def __str__(self): - return "asyncio" - - -_asyncio_runner = _AsyncIORunner() - - -class _AsyncIOProxy: - """Proxy-object for an asyncio - - Any coroutine methods will be wrapped in event_loop.run_ - """ - - def __init__(self, obj, event_loop): - self._obj = obj - self._event_loop = event_loop - - def __repr__(self): - return f"<_AsyncIOProxy({self._obj!r})>" - - def __getattr__(self, key): - attr = getattr(self._obj, key) - if inspect.iscoroutinefunction(attr): - # if it's a coroutine method, - # return a threadsafe wrapper onto the _current_ asyncio loop - @wraps(attr) - def _wrapped(*args, **kwargs): - concurrent_future = asyncio.run_coroutine_threadsafe( - attr(*args, **kwargs), self._event_loop - ) - return asyncio.wrap_future(concurrent_future) - - return _wrapped - else: - return attr - - def __dir__(self): - return dir(self._obj) - - -def _curio_runner(coroutine): - """ - handler for curio autoawait - """ - import curio - - return curio.run(coroutine) - - -def _trio_runner(async_fn): - import trio - - async def loc(coro): - """ - We need the dummy no-op async def to protect from - trio's internal. See https://github.com/python-trio/trio/issues/89 - """ - return await coro - - return trio.run(loc, async_fn) - - -def _pseudo_sync_runner(coro): - """ - A runner that does not really allow async execution, and just advance the coroutine. - - See discussion in https://github.com/python-trio/trio/issues/608, - - Credit to Nathaniel Smith - """ - try: - coro.send(None) - except StopIteration as exc: - return exc.value - else: - # TODO: do not raise but return an execution result with the right info. - raise RuntimeError( - "{coro_name!r} needs a real async loop".format(coro_name=coro.__name__) - ) - - -def _should_be_async(cell: str) -> bool: - """Detect if a block of code need to be wrapped in an `async def` - - Attempt to parse the block of code, it it compile we're fine. - Otherwise we wrap if and try to compile. - - If it works, assume it should be async. Otherwise Return False. - - Not handled yet: If the block of code has a return statement as the top - level, it will be seen as async. This is a know limitation. - """ - try: - code = compile( - cell, "<>", "exec", flags=getattr(ast, "PyCF_ALLOW_TOP_LEVEL_AWAIT", 0x0) - ) - return inspect.CO_COROUTINE & code.co_flags == inspect.CO_COROUTINE - except (SyntaxError, MemoryError): - return False diff --git a/contrib/python/ipython/py3/IPython/core/autocall.py b/contrib/python/ipython/py3/IPython/core/autocall.py deleted file mode 100644 index 54beec3f58..0000000000 --- a/contrib/python/ipython/py3/IPython/core/autocall.py +++ /dev/null @@ -1,70 +0,0 @@ -# encoding: utf-8 -""" -Autocall capabilities for IPython.core. - -Authors: - -* Brian Granger -* Fernando Perez -* Thomas Kluyver - -Notes ------ -""" - -#----------------------------------------------------------------------------- -# Copyright (C) 2008-2011 The IPython Development Team -# -# Distributed under the terms of the BSD License. The full license is in -# the file COPYING, distributed as part of this software. -#----------------------------------------------------------------------------- - -#----------------------------------------------------------------------------- -# Imports -#----------------------------------------------------------------------------- - - -#----------------------------------------------------------------------------- -# Code -#----------------------------------------------------------------------------- - -class IPyAutocall(object): - """ Instances of this class are always autocalled - - This happens regardless of 'autocall' variable state. Use this to - develop macro-like mechanisms. - """ - _ip = None - rewrite = True - def __init__(self, ip=None): - self._ip = ip - - def set_ip(self, ip): - """Will be used to set _ip point to current ipython instance b/f call - - Override this method if you don't want this to happen. - - """ - self._ip = ip - - -class ExitAutocall(IPyAutocall): - """An autocallable object which will be added to the user namespace so that - exit, exit(), quit or quit() are all valid ways to close the shell.""" - rewrite = False - - def __call__(self): - self._ip.ask_exit() - -class ZMQExitAutocall(ExitAutocall): - """Exit IPython. Autocallable, so it needn't be explicitly called. - - Parameters - ---------- - keep_kernel : bool - If True, leave the kernel alive. Otherwise, tell the kernel to exit too - (default). - """ - def __call__(self, keep_kernel=False): - self._ip.keepkernel_on_exit = keep_kernel - self._ip.ask_exit() diff --git a/contrib/python/ipython/py3/IPython/core/builtin_trap.py b/contrib/python/ipython/py3/IPython/core/builtin_trap.py deleted file mode 100644 index a8ea4abcd9..0000000000 --- a/contrib/python/ipython/py3/IPython/core/builtin_trap.py +++ /dev/null @@ -1,86 +0,0 @@ -""" -A context manager for managing things injected into :mod:`builtins`. -""" -# Copyright (c) IPython Development Team. -# Distributed under the terms of the Modified BSD License. -import builtins as builtin_mod - -from traitlets.config.configurable import Configurable - -from traitlets import Instance - - -class __BuiltinUndefined(object): pass -BuiltinUndefined = __BuiltinUndefined() - -class __HideBuiltin(object): pass -HideBuiltin = __HideBuiltin() - - -class BuiltinTrap(Configurable): - - shell = Instance('IPython.core.interactiveshell.InteractiveShellABC', - allow_none=True) - - def __init__(self, shell=None): - super(BuiltinTrap, self).__init__(shell=shell, config=None) - self._orig_builtins = {} - # We define this to track if a single BuiltinTrap is nested. - # Only turn off the trap when the outermost call to __exit__ is made. - self._nested_level = 0 - self.shell = shell - # builtins we always add - if set to HideBuiltin, they will just - # be removed instead of being replaced by something else - self.auto_builtins = {'exit': HideBuiltin, - 'quit': HideBuiltin, - 'get_ipython': self.shell.get_ipython, - } - - def __enter__(self): - if self._nested_level == 0: - self.activate() - self._nested_level += 1 - # I return self, so callers can use add_builtin in a with clause. - return self - - def __exit__(self, type, value, traceback): - if self._nested_level == 1: - self.deactivate() - self._nested_level -= 1 - # Returning False will cause exceptions to propagate - return False - - def add_builtin(self, key, value): - """Add a builtin and save the original.""" - bdict = builtin_mod.__dict__ - orig = bdict.get(key, BuiltinUndefined) - if value is HideBuiltin: - if orig is not BuiltinUndefined: #same as 'key in bdict' - self._orig_builtins[key] = orig - del bdict[key] - else: - self._orig_builtins[key] = orig - bdict[key] = value - - def remove_builtin(self, key, orig): - """Remove an added builtin and re-set the original.""" - if orig is BuiltinUndefined: - del builtin_mod.__dict__[key] - else: - builtin_mod.__dict__[key] = orig - - def activate(self): - """Store ipython references in the __builtin__ namespace.""" - - add_builtin = self.add_builtin - for name, func in self.auto_builtins.items(): - add_builtin(name, func) - - def deactivate(self): - """Remove any builtins which might have been added by add_builtins, or - restore overwritten ones to their previous values.""" - remove_builtin = self.remove_builtin - for key, val in self._orig_builtins.items(): - remove_builtin(key, val) - self._orig_builtins.clear() - self._builtins_added = False diff --git a/contrib/python/ipython/py3/IPython/core/compilerop.py b/contrib/python/ipython/py3/IPython/core/compilerop.py deleted file mode 100644 index b43e570b3a..0000000000 --- a/contrib/python/ipython/py3/IPython/core/compilerop.py +++ /dev/null @@ -1,196 +0,0 @@ -"""Compiler tools with improved interactive support. - -Provides compilation machinery similar to codeop, but with caching support so -we can provide interactive tracebacks. - -Authors -------- -* Robert Kern -* Fernando Perez -* Thomas Kluyver -""" - -# Note: though it might be more natural to name this module 'compiler', that -# name is in the stdlib and name collisions with the stdlib tend to produce -# weird problems (often with third-party tools). - -#----------------------------------------------------------------------------- -# Copyright (C) 2010-2011 The IPython Development Team. -# -# Distributed under the terms of the BSD License. -# -# The full license is in the file COPYING.txt, distributed with this software. -#----------------------------------------------------------------------------- - -#----------------------------------------------------------------------------- -# Imports -#----------------------------------------------------------------------------- - -# Stdlib imports -import __future__ -from ast import PyCF_ONLY_AST -import codeop -import functools -import hashlib -import linecache -import operator -import time -from contextlib import contextmanager - -#----------------------------------------------------------------------------- -# Constants -#----------------------------------------------------------------------------- - -# Roughly equal to PyCF_MASK | PyCF_MASK_OBSOLETE as defined in pythonrun.h, -# this is used as a bitmask to extract future-related code flags. -PyCF_MASK = functools.reduce(operator.or_, - (getattr(__future__, fname).compiler_flag - for fname in __future__.all_feature_names)) - -#----------------------------------------------------------------------------- -# Local utilities -#----------------------------------------------------------------------------- - -def code_name(code, number=0): - """ Compute a (probably) unique name for code for caching. - - This now expects code to be unicode. - """ - hash_digest = hashlib.sha1(code.encode("utf-8")).hexdigest() - # Include the number and 12 characters of the hash in the name. It's - # pretty much impossible that in a single session we'll have collisions - # even with truncated hashes, and the full one makes tracebacks too long - return '<ipython-input-{0}-{1}>'.format(number, hash_digest[:12]) - -#----------------------------------------------------------------------------- -# Classes and functions -#----------------------------------------------------------------------------- - -class CachingCompiler(codeop.Compile): - """A compiler that caches code compiled from interactive statements. - """ - - def __init__(self): - codeop.Compile.__init__(self) - - # This is ugly, but it must be done this way to allow multiple - # simultaneous ipython instances to coexist. Since Python itself - # directly accesses the data structures in the linecache module, and - # the cache therein is global, we must work with that data structure. - # We must hold a reference to the original checkcache routine and call - # that in our own check_cache() below, but the special IPython cache - # must also be shared by all IPython instances. If we were to hold - # separate caches (one in each CachingCompiler instance), any call made - # by Python itself to linecache.checkcache() would obliterate the - # cached data from the other IPython instances. - if not hasattr(linecache, '_ipython_cache'): - linecache._ipython_cache = {} - if not hasattr(linecache, '_checkcache_ori'): - linecache._checkcache_ori = linecache.checkcache - # Now, we must monkeypatch the linecache directly so that parts of the - # stdlib that call it outside our control go through our codepath - # (otherwise we'd lose our tracebacks). - linecache.checkcache = check_linecache_ipython - - # Caching a dictionary { filename: execution_count } for nicely - # rendered tracebacks. The filename corresponds to the filename - # argument used for the builtins.compile function. - self._filename_map = {} - - def ast_parse(self, source, filename='<unknown>', symbol='exec'): - """Parse code to an AST with the current compiler flags active. - - Arguments are exactly the same as ast.parse (in the standard library), - and are passed to the built-in compile function.""" - return compile(source, filename, symbol, self.flags | PyCF_ONLY_AST, 1) - - def reset_compiler_flags(self): - """Reset compiler flags to default state.""" - # This value is copied from codeop.Compile.__init__, so if that ever - # changes, it will need to be updated. - self.flags = codeop.PyCF_DONT_IMPLY_DEDENT - - @property - def compiler_flags(self): - """Flags currently active in the compilation process. - """ - return self.flags - - def get_code_name(self, raw_code, transformed_code, number): - """Compute filename given the code, and the cell number. - - Parameters - ---------- - raw_code : str - The raw cell code. - transformed_code : str - The executable Python source code to cache and compile. - number : int - A number which forms part of the code's name. Used for the execution - counter. - - Returns - ------- - The computed filename. - """ - return code_name(transformed_code, number) - - def cache(self, transformed_code, number=0, raw_code=None): - """Make a name for a block of code, and cache the code. - - Parameters - ---------- - transformed_code : str - The executable Python source code to cache and compile. - number : int - A number which forms part of the code's name. Used for the execution - counter. - raw_code : str - The raw code before transformation, if None, set to `transformed_code`. - - Returns - ------- - The name of the cached code (as a string). Pass this as the filename - argument to compilation, so that tracebacks are correctly hooked up. - """ - if raw_code is None: - raw_code = transformed_code - - name = self.get_code_name(raw_code, transformed_code, number) - - # Save the execution count - self._filename_map[name] = number - - entry = ( - len(transformed_code), - time.time(), - [line + "\n" for line in transformed_code.splitlines()], - name, - ) - linecache.cache[name] = entry - linecache._ipython_cache[name] = entry - return name - - @contextmanager - def extra_flags(self, flags): - ## bits that we'll set to 1 - turn_on_bits = ~self.flags & flags - - - self.flags = self.flags | flags - try: - yield - finally: - # turn off only the bits we turned on so that something like - # __future__ that set flags stays. - self.flags &= ~turn_on_bits - - -def check_linecache_ipython(*args): - """Call linecache.checkcache() safely protecting our cached values. - """ - # First call the original checkcache as intended - linecache._checkcache_ori(*args) - # Then, update back the cache with our data, so that tracebacks related - # to our compiled codes can be produced. - linecache.cache.update(linecache._ipython_cache) diff --git a/contrib/python/ipython/py3/IPython/core/completer.py b/contrib/python/ipython/py3/IPython/core/completer.py deleted file mode 100644 index fcc9d20d59..0000000000 --- a/contrib/python/ipython/py3/IPython/core/completer.py +++ /dev/null @@ -1,2273 +0,0 @@ -"""Completion for IPython. - -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, - -This module now support a wide variety of completion mechanism both available -for normal classic Python code, as well as completer for IPython specific -Syntax like magics. - -Latex and Unicode completion -============================ - -IPython and compatible frontends not only can complete your code, but can help -you to input a wide range of characters. In particular we allow you to insert -a unicode character using the tab completion mechanism. - -Forward latex/unicode completion --------------------------------- - -Forward completion allows you to easily type a unicode character using its latex -name, or unicode long description. To do so type a backslash follow by the -relevant name and press tab: - - -Using latex completion: - -.. code:: - - \\alpha<tab> - α - -or using unicode completion: - - -.. code:: - - \\GREEK SMALL LETTER ALPHA<tab> - α - - -Only valid Python identifiers will complete. Combining characters (like arrow or -dots) are also available, unlike latex they need to be put after the their -counterpart that is to say, ``F\\\\vec<tab>`` is correct, not ``\\\\vec<tab>F``. - -Some browsers are known to display combining characters incorrectly. - -Backward latex completion -------------------------- - -It is sometime challenging to know how to type a character, if you are using -IPython, or any compatible frontend you can prepend backslash to the character -and press ``<tab>`` to expand it to its latex form. - -.. code:: - - \\α<tab> - \\alpha - - -Both forward and backward completions can be deactivated by setting the -``Completer.backslash_combining_completions`` option to ``False``. - - -Experimental -============ - -Starting with IPython 6.0, this module can make use of the Jedi library to -generate completions both using static analysis of the code, and dynamically -inspecting multiple namespaces. Jedi is an autocompletion and static analysis -for Python. The APIs attached to this new mechanism is unstable and will -raise unless use in an :any:`provisionalcompleter` context manager. - -You will find that the following are experimental: - - - :any:`provisionalcompleter` - - :any:`IPCompleter.completions` - - :any:`Completion` - - :any:`rectify_completions` - -.. note:: - - better name for :any:`rectify_completions` ? - -We welcome any feedback on these new API, and we also encourage you to try this -module in debug mode (start IPython with ``--Completer.debug=True``) in order -to have extra logging information if :any:`jedi` is crashing, or if current -IPython completer pending deprecations are returning results not yet handled -by :any:`jedi` - -Using Jedi for tab completion allow snippets like the following to work without -having to execute any code: - - >>> myvar = ['hello', 42] - ... myvar[1].bi<tab> - -Tab completion will be able to infer that ``myvar[1]`` is a real number without -executing any code unlike the previously available ``IPCompleter.greedy`` -option. - -Be sure to update :any:`jedi` to the latest stable version or to try the -current development version to get better completions. -""" - - -# Copyright (c) IPython Development Team. -# Distributed under the terms of the Modified BSD License. -# -# Some of this code originated from rlcompleter in the Python standard library -# Copyright (C) 2001 Python Software Foundation, www.python.org - - -import builtins as builtin_mod -import glob -import inspect -import itertools -import keyword -import os -import re -import string -import sys -import time -import unicodedata -import uuid -import warnings -from contextlib import contextmanager -from importlib import import_module -from types import SimpleNamespace -from typing import Iterable, Iterator, List, Tuple, Union, Any, Sequence, Dict, NamedTuple, Pattern, Optional - -from IPython.core.error import TryNext -from IPython.core.inputtransformer2 import ESC_MAGIC -from IPython.core.latex_symbols import latex_symbols, reverse_latex_symbol -from IPython.core.oinspect import InspectColors -from IPython.testing.skipdoctest import skip_doctest -from IPython.utils import generics -from IPython.utils.dir2 import dir2, get_real_method -from IPython.utils.path import ensure_dir_exists -from IPython.utils.process import arg_split -from traitlets import Bool, Enum, Int, List as ListTrait, Unicode, default, observe -from traitlets.config.configurable import Configurable - -import __main__ - -# skip module docstests -__skip_doctest__ = True - -try: - import jedi - jedi.settings.case_insensitive_completion = False - import jedi.api.helpers - import jedi.api.classes - JEDI_INSTALLED = True -except ImportError: - JEDI_INSTALLED = False -#----------------------------------------------------------------------------- -# Globals -#----------------------------------------------------------------------------- - -# ranges where we have most of the valid unicode names. We could be more finer -# grained but is it worth it for performance While unicode have character in the -# range 0, 0x110000, we seem to have name for about 10% of those. (131808 as I -# write this). With below range we cover them all, with a density of ~67% -# biggest next gap we consider only adds up about 1% density and there are 600 -# gaps that would need hard coding. -_UNICODE_RANGES = [(32, 0x3134b), (0xe0001, 0xe01f0)] - -# Public API -__all__ = ['Completer','IPCompleter'] - -if sys.platform == 'win32': - PROTECTABLES = ' ' -else: - PROTECTABLES = ' ()[]{}?=\\|;:\'#*"^&' - -# Protect against returning an enormous number of completions which the frontend -# may have trouble processing. -MATCHES_LIMIT = 500 - - -class ProvisionalCompleterWarning(FutureWarning): - """ - Exception raise by an experimental feature in this module. - - Wrap code in :any:`provisionalcompleter` context manager if you - are certain you want to use an unstable feature. - """ - pass - -warnings.filterwarnings('error', category=ProvisionalCompleterWarning) - - -@skip_doctest -@contextmanager -def provisionalcompleter(action='ignore'): - """ - This context manager has to be used in any place where unstable completer - behavior and API may be called. - - >>> with provisionalcompleter(): - ... completer.do_experimental_things() # works - - >>> completer.do_experimental_things() # raises. - - .. note:: - - Unstable - - By using this context manager you agree that the API in use may change - without warning, and that you won't complain if they do so. - - You also understand that, if the API is not to your liking, you should report - a bug to explain your use case upstream. - - We'll be happy to get your feedback, feature requests, and improvements on - any of the unstable APIs! - """ - with warnings.catch_warnings(): - warnings.filterwarnings(action, category=ProvisionalCompleterWarning) - yield - - -def has_open_quotes(s): - """Return whether a string has open quotes. - - This simply counts whether the number of quote characters of either type in - the string is odd. - - Returns - ------- - If there is an open quote, the quote character is returned. Else, return - False. - """ - # We check " first, then ', so complex cases with nested quotes will get - # the " to take precedence. - if s.count('"') % 2: - return '"' - elif s.count("'") % 2: - return "'" - else: - return False - - -def protect_filename(s, protectables=PROTECTABLES): - """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 - - -def expand_user(path:str) -> Tuple[str, bool, str]: - """Expand ``~``-style usernames in strings. - - This is similar to :func:`os.path.expanduser`, but it computes and returns - extra information that will be useful if the input was being used in - computing completions, and you wish to return the completions with the - original '~' instead of its expanded value. - - Parameters - ---------- - path : str - String to be expanded. If no ~ is present, the output is the same as the - input. - - Returns - ------- - newpath : str - Result of ~ expansion in the input path. - tilde_expand : bool - Whether any expansion was performed or not. - tilde_val : str - The value that ~ was replaced with. - """ - # Default values - tilde_expand = False - tilde_val = '' - newpath = path - - if path.startswith('~'): - tilde_expand = True - rest = len(path)-1 - newpath = os.path.expanduser(path) - if rest: - tilde_val = newpath[:-rest] - else: - tilde_val = newpath - - return newpath, tilde_expand, tilde_val - - -def compress_user(path:str, tilde_expand:bool, tilde_val:str) -> str: - """Does the opposite of expand_user, with its outputs. - """ - if tilde_expand: - return path.replace(tilde_val, '~') - else: - return path - - -def completions_sorting_key(word): - """key for sorting completions - - This does several things: - - - Demote any completions starting with underscores to the end - - Insert any %magic and %%cellmagic completions in the alphabetical order - by their name - """ - prio1, prio2 = 0, 0 - - if word.startswith('__'): - prio1 = 2 - elif word.startswith('_'): - 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 not "%" in word[2:]: - word = word[2:] - prio2 = 2 - elif word.startswith('%'): - if not "%" in word[1:]: - word = word[1:] - prio2 = 1 - - return prio1, word, prio2 - - -class _FakeJediCompletion: - """ - This is a workaround to communicate to the UI that Jedi has crashed and to - report a bug. Will be used only id :any:`IPCompleter.debug` is set to true. - - Added in IPython 6.0 so should likely be removed for 7.0 - - """ - - def __init__(self, name): - - self.name = name - self.complete = name - self.type = 'crashed' - self.name_with_symbols = name - self.signature = '' - self._origin = 'fake' - - def __repr__(self): - return '<Fake completion object jedi has crashed>' - - -class Completion: - """ - Completion object used and return by IPython completers. - - .. warning:: - - Unstable - - This function is unstable, API may change without warning. - It will also raise unless use in proper context manager. - - This act as a middle ground :any:`Completion` object between the - :any:`jedi.api.classes.Completion` object and the Prompt Toolkit completion - object. While Jedi need a lot of information about evaluator and how the - code should be ran/inspected, PromptToolkit (and other frontend) mostly - need user facing information. - - - Which range should be replaced replaced by what. - - Some metadata (like completion type), or meta information to displayed to - the use user. - - For debugging purpose we can also store the origin of the completion (``jedi``, - ``IPython.python_matches``, ``IPython.magics_matches``...). - """ - - __slots__ = ['start', 'end', 'text', 'type', 'signature', '_origin'] - - def __init__(self, start: int, end: int, text: str, *, type: str=None, _origin='', signature='') -> None: - warnings.warn("``Completion`` is a provisional API (as of IPython 6.0). " - "It may change without warnings. " - "Use in corresponding context manager.", - category=ProvisionalCompleterWarning, stacklevel=2) - - self.start = start - self.end = end - self.text = text - self.type = type - self.signature = signature - self._origin = _origin - - def __repr__(self): - return '<Completion start=%s end=%s text=%r type=%r, signature=%r,>' % \ - (self.start, self.end, self.text, self.type or '?', self.signature or '?') - - def __eq__(self, other)->Bool: - """ - Equality and hash do not hash the type (as some completer may not be - able to infer the type), but are use to (partially) de-duplicate - completion. - - Completely de-duplicating completion is a bit tricker that just - comparing as it depends on surrounding text, which Completions are not - aware of. - """ - return self.start == other.start and \ - self.end == other.end and \ - self.text == other.text - - def __hash__(self): - return hash((self.start, self.end, self.text)) - - -_IC = Iterable[Completion] - - -def _deduplicate_completions(text: str, completions: _IC)-> _IC: - """ - Deduplicate a set of completions. - - .. warning:: - - Unstable - - This function is unstable, API may change without warning. - - Parameters - ---------- - text : str - text that should be completed. - completions : Iterator[Completion] - iterator over the completions to deduplicate - - Yields - ------ - `Completions` objects - Completions coming from multiple sources, may be different but end up having - the same effect when applied to ``text``. If this is the case, this will - consider completions as equal and only emit the first encountered. - Not folded in `completions()` yet for debugging purpose, and to detect when - the IPython completer does return things that Jedi does not, but should be - at some point. - """ - completions = list(completions) - if not completions: - return - - new_start = min(c.start for c in completions) - new_end = max(c.end for c in completions) - - seen = set() - for c in completions: - new_text = text[new_start:c.start] + c.text + text[c.end:new_end] - if new_text not in seen: - yield c - seen.add(new_text) - - -def rectify_completions(text: str, completions: _IC, *, _debug: bool = False) -> _IC: - """ - Rectify a set of completions to all have the same ``start`` and ``end`` - - .. warning:: - - Unstable - - This function is unstable, API may change without warning. - It will also raise unless use in proper context manager. - - Parameters - ---------- - text : str - text that should be completed. - completions : Iterator[Completion] - iterator over the completions to rectify - _debug : bool - Log failed completion - - Notes - ----- - :any:`jedi.api.classes.Completion` s returned by Jedi may not have the same start and end, though - the Jupyter Protocol requires them to behave like so. This will readjust - the completion to have the same ``start`` and ``end`` by padding both - extremities with surrounding text. - - During stabilisation should support a ``_debug`` option to log which - completion are return by the IPython completer and not found in Jedi in - order to make upstream bug report. - """ - warnings.warn("`rectify_completions` is a provisional API (as of IPython 6.0). " - "It may change without warnings. " - "Use in corresponding context manager.", - category=ProvisionalCompleterWarning, stacklevel=2) - - completions = list(completions) - if not completions: - return - starts = (c.start for c in completions) - ends = (c.end for c in completions) - - new_start = min(starts) - new_end = max(ends) - - seen_jedi = set() - seen_python_matches = set() - for c in completions: - new_text = text[new_start:c.start] + c.text + text[c.end:new_end] - if c._origin == 'jedi': - seen_jedi.add(new_text) - elif c._origin == 'IPCompleter.python_matches': - seen_python_matches.add(new_text) - yield Completion(new_start, new_end, new_text, type=c.type, _origin=c._origin, signature=c.signature) - diff = seen_python_matches.difference(seen_jedi) - if diff and _debug: - print('IPython.python matches have extras:', diff) - - -if sys.platform == 'win32': - DELIMS = ' \t\n`!@#$^&*()=+[{]}|;\'",<>?' -else: - DELIMS = ' \t\n`!@#$^&*()=+[{]}\\|;:\'",<>?' - -GREEDY_DELIMS = ' =\r\n' - - -class CompletionSplitter(object): - """An object to split an input line in a manner similar to readline. - - By having our own implementation, we can expose readline-like completion in - a uniform manner to all frontends. This object only needs to be given the - line of text to be split and the cursor position on said line, and it - returns the 'word' to be completed on at the cursor after splitting the - entire line. - - What characters are used as splitting delimiters can be controlled by - setting the ``delims`` attribute (this is a property that internally - automatically builds the necessary regular expression)""" - - # Private interface - - # A string of delimiter characters. The default value makes sense for - # IPython's most typical usage patterns. - _delims = DELIMS - - # The expression (a normal string) to be compiled into a regular expression - # for actual splitting. We store it as an attribute mostly for ease of - # debugging, since this type of code can be so tricky to debug. - _delim_expr = None - - # The regular expression that does the actual splitting - _delim_re = None - - def __init__(self, delims=None): - delims = CompletionSplitter._delims if delims is None else delims - self.delims = delims - - @property - def delims(self): - """Return the string of delimiter characters.""" - return self._delims - - @delims.setter - def delims(self, delims): - """Set the delimiters for line splitting.""" - expr = '[' + ''.join('\\'+ c for c in delims) + ']' - self._delim_re = re.compile(expr) - self._delims = delims - self._delim_expr = expr - - def split_line(self, line, cursor_pos=None): - """Split a line of text with a cursor at the given position. - """ - l = line if cursor_pos is None else line[:cursor_pos] - return self._delim_re.split(l)[-1] - - - -class Completer(Configurable): - - greedy = Bool(False, - help="""Activate greedy completion - PENDING DEPRECATION. 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) - - use_jedi = Bool(default_value=JEDI_INSTALLED, - help="Experimental: Use Jedi to generate autocompletions. " - "Default to True if jedi is installed.").tag(config=True) - - jedi_compute_type_timeout = Int(default_value=400, - help="""Experimental: restrict time (in milliseconds) during which Jedi can compute types. - Set to 0 to stop computing types. Non-zero value lower than 100ms may hurt - performance by preventing jedi to build its cache. - """).tag(config=True) - - debug = Bool(default_value=False, - help='Enable debug for the Completer. Mostly print extra ' - 'information for experimental jedi integration.')\ - .tag(config=True) - - backslash_combining_completions = Bool(True, - help="Enable unicode completions, e.g. \\alpha<tab> . " - "Includes completion of latex commands, unicode names, and expanding " - "unicode characters back to latex commands.").tag(config=True) - - 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. - - If unspecified, the default namespace where completions are performed - is __main__ (technically, __main__.__dict__). Namespaces should be - given as dictionaries. - - An optional second namespace can be given. This allows the completer - to handle cases where both the local and global scopes need to be - distinguished. - """ - - # Don't bind to namespace quite yet, but flag whether the user wants a - # specific namespace or to use __main__.__dict__. This will allow us - # to bind to __main__.__dict__ at completion time, not now. - if namespace is None: - self.use_main_ns = True - else: - self.use_main_ns = False - self.namespace = namespace - - # The global namespace, if given, can be bound directly - if global_namespace is None: - self.global_namespace = {} - else: - self.global_namespace = global_namespace - - self.custom_matchers = [] - - super(Completer, self).__init__(**kwargs) - - def complete(self, text, state): - """Return the next possible completion for 'text'. - - This is called successively with state == 0, 1, 2, ... until it - returns None. The completion should begin with 'text'. - - """ - if self.use_main_ns: - self.namespace = __main__.__dict__ - - if state == 0: - if "." in text: - self.matches = self.attr_matches(text) - else: - self.matches = self.global_matches(text) - try: - return self.matches[state] - except IndexError: - return None - - def global_matches(self, text): - """Compute matches when text is a simple name. - - Return a list of all keywords, built-in functions and names currently - defined in self.namespace or self.global_namespace that match. - - """ - matches = [] - match_append = matches.append - n = len(text) - for lst in [keyword.kwlist, - builtin_mod.__dict__.keys(), - self.namespace.keys(), - self.global_namespace.keys()]: - for word in lst: - if word[:n] == text and word != "__builtins__": - match_append(word) - - snake_case_re = re.compile(r"[^_]+(_[^_]+)+?\Z") - for lst in [self.namespace.keys(), - self.global_namespace.keys()]: - shortened = {"_".join([sub[0] for sub in word.split('_')]) : word - for word in lst if snake_case_re.match(word)} - for word in shortened.keys(): - if word[:n] == text and word != "__builtins__": - match_append(shortened[word]) - return matches - - def attr_matches(self, text): - """Compute matches when text contains a dot. - - Assuming the text is of the form NAME.NAME....[NAME], and is - evaluatable in self.namespace or self.global_namespace, it will be - evaluated and its attributes (as revealed by dir()) are used as - possible completions. (For class instances, class members are - also considered.) - - WARNING: this can still invoke arbitrary C code, if an object - with a __getattr__ hook is evaluated. - - """ - - # Another option, seems to work great. Catches things like ''.<tab> - m = re.match(r"(\S+(\.\w+)*)\.(\w*)$", text) - - if m: - expr, attr = m.group(1, 3) - elif self.greedy: - m2 = re.match(r"(.+)\.(\w*)$", self.line_buffer) - if not m2: - return [] - expr, attr = m2.group(1,2) - else: - return [] - - try: - obj = eval(expr, self.namespace) - except: - try: - obj = eval(expr, self.global_namespace) - except: - return [] - - if self.limit_to__all__ and hasattr(obj, '__all__'): - words = get__all__entries(obj) - else: - words = dir2(obj) - - try: - words = generics.complete_object(obj, words) - except TryNext: - pass - except AssertionError: - raise - except Exception: - # Silence errors from completion function - #raise # dbg - pass - # Build match list to return - n = len(attr) - return [u"%s.%s" % (expr, w) for w in words if w[:n] == attr ] - - -def get__all__entries(obj): - """returns the strings in the __all__ attribute""" - try: - words = getattr(obj, '__all__') - except: - return [] - - return [w for w in words if isinstance(w, str)] - - -def match_dict_keys(keys: List[Union[str, bytes, Tuple[Union[str, bytes]]]], prefix: str, delims: str, - extra_prefix: Optional[Tuple[str, bytes]]=None) -> Tuple[str, int, List[str]]: - """Used by dict_key_matches, matching the prefix to a list of keys - - Parameters - ---------- - keys - list of keys in dictionary currently being completed. - prefix - Part of the text already typed by the user. E.g. `mydict[b'fo` - delims - String of delimiters to consider when finding the current key. - extra_prefix : optional - Part of the text already typed in multi-key index cases. E.g. for - `mydict['foo', "bar", 'b`, this would be `('foo', 'bar')`. - - Returns - ------- - A tuple of three elements: ``quote``, ``token_start``, ``matched``, with - ``quote`` being the quote that need to be used to close current string. - ``token_start`` the position where the replacement should start occurring, - ``matches`` a list of replacement/completion - - """ - prefix_tuple = extra_prefix if extra_prefix else () - Nprefix = len(prefix_tuple) - def filter_prefix_tuple(key): - # Reject too short keys - if len(key) <= Nprefix: - return False - # Reject keys with non str/bytes in it - for k in key: - if not isinstance(k, (str, bytes)): - return False - # Reject keys that do not match the prefix - for k, pt in zip(key, prefix_tuple): - if k != pt: - return False - # All checks passed! - return True - - filtered_keys:List[Union[str,bytes]] = [] - def _add_to_filtered_keys(key): - if isinstance(key, (str, bytes)): - filtered_keys.append(key) - - for k in keys: - if isinstance(k, tuple): - if filter_prefix_tuple(k): - _add_to_filtered_keys(k[Nprefix]) - else: - _add_to_filtered_keys(k) - - if not prefix: - return '', 0, [repr(k) for k in filtered_keys] - quote_match = re.search('["\']', prefix) - assert quote_match is not None # silence mypy - quote = quote_match.group() - try: - prefix_str = eval(prefix + quote, {}) - except Exception: - return '', 0, [] - - pattern = '[^' + ''.join('\\' + c for c in delims) + ']*$' - token_match = re.search(pattern, prefix, re.UNICODE) - assert token_match is not None # silence mypy - token_start = token_match.start() - token_prefix = token_match.group() - - matched:List[str] = [] - for key in filtered_keys: - try: - if not key.startswith(prefix_str): - continue - except (AttributeError, TypeError, UnicodeError): - # Python 3+ TypeError on b'a'.startswith('a') or vice-versa - continue - - # reformat remainder of key to begin with prefix - rem = key[len(prefix_str):] - # force repr wrapped in ' - rem_repr = repr(rem + '"') if isinstance(rem, str) else repr(rem + b'"') - rem_repr = rem_repr[1 + rem_repr.index("'"):-2] - if quote == '"': - # The entered prefix is quoted with ", - # but the match is quoted with '. - # A contained " hence needs escaping for comparison: - rem_repr = rem_repr.replace('"', '\\"') - - # then reinsert prefix from start of token - matched.append('%s%s' % (token_prefix, rem_repr)) - return quote, token_start, matched - - -def cursor_to_position(text:str, line:int, column:int)->int: - """ - Convert the (line,column) position of the cursor in text to an offset in a - string. - - Parameters - ---------- - text : str - The text in which to calculate the cursor offset - line : int - Line of the cursor; 0-indexed - column : int - Column of the cursor 0-indexed - - Returns - ------- - Position of the cursor in ``text``, 0-indexed. - - See Also - -------- - position_to_cursor : reciprocal of this function - - """ - lines = text.split('\n') - assert line <= len(lines), '{} <= {}'.format(str(line), str(len(lines))) - - return sum(len(l) + 1 for l in lines[:line]) + column - -def position_to_cursor(text:str, offset:int)->Tuple[int, int]: - """ - Convert the position of the cursor in text (0 indexed) to a line - number(0-indexed) and a column number (0-indexed) pair - - Position should be a valid position in ``text``. - - Parameters - ---------- - text : str - The text in which to calculate the cursor offset - offset : int - Position of the cursor in ``text``, 0-indexed. - - Returns - ------- - (line, column) : (int, int) - Line of the cursor; 0-indexed, column of the cursor 0-indexed - - See Also - -------- - cursor_to_position : reciprocal of this function - - """ - - assert 0 <= offset <= len(text) , "0 <= %s <= %s" % (offset , len(text)) - - before = text[:offset] - blines = before.split('\n') # ! splitnes trim trailing \n - line = before.count('\n') - col = len(blines[-1]) - return line, col - - -def _safe_isinstance(obj, module, class_name): - """Checks if obj is an instance of module.class_name if loaded - """ - return (module in sys.modules and - isinstance(obj, getattr(import_module(module), class_name))) - -def back_unicode_name_matches(text:str) -> Tuple[str, Sequence[str]]: - """Match Unicode characters back to Unicode name - - This does ``☃`` -> ``\\snowman`` - - Note that snowman is not a valid python3 combining character but will be expanded. - Though it will not recombine back to the snowman character by the completion machinery. - - This will not either back-complete standard sequences like \\n, \\b ... - - Returns - ======= - - Return a tuple with two elements: - - - The Unicode character that was matched (preceded with a backslash), or - empty string, - - a sequence (of 1), name for the match Unicode character, preceded by - backslash, or empty if no match. - - """ - if len(text)<2: - return '', () - maybe_slash = text[-2] - if maybe_slash != '\\': - return '', () - - char = text[-1] - # no expand on quote for completion in strings. - # nor backcomplete standard ascii keys - if char in string.ascii_letters or char in ('"',"'"): - return '', () - try : - unic = unicodedata.name(char) - return '\\'+char,('\\'+unic,) - except KeyError: - pass - return '', () - -def back_latex_name_matches(text:str) -> Tuple[str, Sequence[str]] : - """Match latex characters back to unicode name - - This does ``\\ℵ`` -> ``\\aleph`` - - """ - if len(text)<2: - return '', () - maybe_slash = text[-2] - if maybe_slash != '\\': - return '', () - - - char = text[-1] - # no expand on quote for completion in strings. - # nor backcomplete standard ascii keys - if char in string.ascii_letters or char in ('"',"'"): - return '', () - try : - latex = reverse_latex_symbol[char] - # '\\' replace the \ as well - return '\\'+char,[latex] - except KeyError: - pass - return '', () - - -def _formatparamchildren(parameter) -> str: - """ - Get parameter name and value from Jedi Private API - - Jedi does not expose a simple way to get `param=value` from its API. - - Parameters - ---------- - parameter - Jedi's function `Param` - - Returns - ------- - A string like 'a', 'b=1', '*args', '**kwargs' - - """ - description = parameter.description - if not description.startswith('param '): - raise ValueError('Jedi function parameter description have change format.' - 'Expected "param ...", found %r".' % description) - return description[6:] - -def _make_signature(completion)-> str: - """ - Make the signature from a jedi completion - - Parameters - ---------- - completion : jedi.Completion - object does not complete a function type - - Returns - ------- - a string consisting of the function signature, with the parenthesis but - without the function name. example: - `(a, *args, b=1, **kwargs)` - - """ - - return '(%s)'% ', '.join([f for f in (_formatparamchildren(p) for p in completion.params) if f]) - # it looks like this might work on jedi 0.17 - if hasattr(completion, 'get_signatures'): - signatures = completion.get_signatures() - if not signatures: - return '(?)' - - c0 = completion.get_signatures()[0] - return '('+c0.to_string().split('(', maxsplit=1)[1] - - return '(%s)'% ', '.join([f for f in (_formatparamchildren(p) for signature in completion.get_signatures() - for p in signature.defined_names()) if f]) - - -class _CompleteResult(NamedTuple): - matched_text : str - matches: Sequence[str] - matches_origin: Sequence[str] - jedi_matches: Any - - -class IPCompleter(Completer): - """Extension of the completer class with IPython-specific features""" - - __dict_key_regexps: Optional[Dict[bool,Pattern]] = None - - @observe('greedy') - def _greedy_changed(self, change): - """update the splitter and readline delims when greedy is changed""" - if change['new']: - self.splitter.delims = GREEDY_DELIMS - else: - self.splitter.delims = DELIMS - - dict_keys_only = Bool(False, - help="""Whether to show dict key matches only""") - - 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, - help="""Instruct the completer to omit private method names - - Specifically, when completing on ``object.<tab>``. - - When 2 [default]: all names that start with '_' will be excluded. - - When 1: all 'magic' names (``__foo__``) will be excluded. - - 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 - - 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) - - profile_completions = Bool( - default_value=False, - help="If True, emit profiling data for completion subsystem using cProfile." - ).tag(config=True) - - profiler_output_dir = Unicode( - default_value=".completion_profiles", - help="Template for path at which to output profile data for completions." - ).tag(config=True) - - @observe('limit_to__all__') - def _limit_to_all_changed(self, change): - warnings.warn('`IPython.core.IPCompleter.limit_to__all__` configuration ' - 'value has been deprecated since IPython 5.0, will be made to have ' - 'no effects and then removed in future version of IPython.', - UserWarning) - - def __init__( - self, shell=None, namespace=None, global_namespace=None, config=None, **kwargs - ): - """IPCompleter() -> completer - - Return a completer object. - - Parameters - ---------- - shell - a pointer to the ipython shell itself. This is needed - because this completer knows about magic functions, and those can - only be accessed via the ipython instance. - namespace : dict, optional - an optional dict where completions are performed. - global_namespace : dict, optional - secondary optional dict for completions, to - handle cases (such as IPython embedded inside functions) where - both Python scopes are visible. - config : Config - traitlet's config object - **kwargs - passed to super class unmodified. - """ - - self.magic_escape = ESC_MAGIC - self.splitter = CompletionSplitter() - - # _greedy_changed() depends on splitter and readline being defined: - super().__init__( - namespace=namespace, - global_namespace=global_namespace, - config=config, - **kwargs - ) - - # List where completion matches will be stored - self.matches = [] - self.shell = shell - # Regexp to split filenames with spaces in them - self.space_name_re = re.compile(r'([^\\] )') - # Hold a local ref. to glob.glob for speed - self.glob = glob.glob - - # Determine if we are running on 'dumb' terminals, like (X)Emacs - # buffers, to avoid completion problems. - term = os.environ.get('TERM','xterm') - self.dumb_terminal = term in ['dumb','emacs'] - - # Special handling of backslashes needed in win32 platforms - if sys.platform == "win32": - self.clean_glob = self._clean_glob_win32 - else: - self.clean_glob = self._clean_glob - - #regexp to parse docstring for function signature - self.docstring_sig_re = re.compile(r'^[\w|\s.]+\(([^)]*)\).*') - self.docstring_kwd_re = re.compile(r'[\s|\[]*(\w+)(?:\s*=\s*.*)') - #use this if positional argument name is also needed - #= re.compile(r'[\s|\[]*(\w+)(?:\s*=?\s*.*)') - - self.magic_arg_matchers = [ - self.magic_config_matches, - self.magic_color_matches, - ] - - # This is set externally by InteractiveShell - self.custom_completers = None - - # This is a list of names of unicode characters that can be completed - # into their corresponding unicode value. The list is large, so we - # lazily initialize it on first use. Consuming code should access this - # attribute through the `@unicode_names` property. - self._unicode_names = None - - @property - def matchers(self) -> List[Any]: - """All active matcher routines for completion""" - if self.dict_keys_only: - return [self.dict_key_matches] - - if self.use_jedi: - return [ - *self.custom_matchers, - self.dict_key_matches, - self.file_matches, - self.magic_matches, - ] - else: - return [ - *self.custom_matchers, - self.dict_key_matches, - self.python_matches, - self.file_matches, - self.magic_matches, - self.python_func_kw_matches, - ] - - def all_completions(self, text:str) -> List[str]: - """ - Wrapper around the completion methods for the benefit of emacs. - """ - prefix = text.rpartition('.')[0] - with provisionalcompleter(): - return ['.'.join([prefix, c.text]) if prefix and self.use_jedi else c.text - for c in self.completions(text, len(text))] - - return self.complete(text)[1] - - def _clean_glob(self, text:str): - return self.glob("%s*" % text) - - def _clean_glob_win32(self, text:str): - return [f.replace("\\","/") - for f in self.glob("%s*" % text)] - - def file_matches(self, text:str)->List[str]: - """Match filenames, expanding ~USER type strings. - - Most of the seemingly convoluted logic in this completer is an - attempt to handle filenames with spaces in them. And yet it's not - quite perfect, because Python's readline doesn't expose all of the - GNU readline details needed for this to be done correctly. - - For a filename with a space in it, the printed completions will be - only the parts after what's already been typed (instead of the - full completions, as is normally done). I don't think with the - current (as of Python 2.3) Python readline it's possible to do - better.""" - - # chars that require escaping with backslash - i.e. chars - # that readline treats incorrectly as delimiters, but we - # don't want to treat as delimiters in filename matching - # when escaped with backslash - if text.startswith('!'): - text = text[1:] - text_prefix = u'!' - else: - text_prefix = u'' - - text_until_cursor = self.text_until_cursor - # track strings with open quotes - open_quotes = has_open_quotes(text_until_cursor) - - if '(' in text_until_cursor or '[' in text_until_cursor: - lsplit = text - else: - try: - # arg_split ~ shlex.split, but with unicode bugs fixed by us - lsplit = arg_split(text_until_cursor)[-1] - except ValueError: - # typically an unmatched ", or backslash without escaped char. - if open_quotes: - lsplit = text_until_cursor.split(open_quotes)[-1] - else: - return [] - except IndexError: - # tab pressed on empty line - lsplit = "" - - if not open_quotes and lsplit != protect_filename(lsplit): - # if protectables are found, do matching on the whole escaped name - has_protectables = True - text0,text = text,lsplit - else: - has_protectables = False - text = os.path.expanduser(text) - - if text == "": - return [text_prefix + 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 has_protectables: - # If we had protectables, we need to revert our changes to the - # beginning of filename so that we don't double-write the part - # of the filename we have so far - len_lsplit = len(lsplit) - matches = [text_prefix + text0 + - protect_filename(f[len_lsplit:]) for f in m0] - else: - if open_quotes: - # if we have a string with an open quote, we don't need to - # protect the names beyond the quote (and we _shouldn't_, as - # it would cause bugs when the filesystem call is made). - matches = m0 if sys.platform == "win32" else\ - [protect_filename(f, open_quotes) for f in m0] - else: - matches = [text_prefix + - protect_filename(f) for f in m0] - - # Mark directories in input list by appending '/' to their names. - return [x+'/' if os.path.isdir(x) else x for x in matches] - - def magic_matches(self, text:str): - """Match magics""" - # Get all shell magics now rather than statically, so magics loaded at - # runtime show up too. - lsm = self.shell.magics_manager.lsmagic() - line_magics = lsm['line'] - cell_magics = lsm['cell'] - pre = self.magic_escape - pre2 = pre+pre - - explicit_magic = text.startswith(pre) - - # Completion logic: - # - user gives %%: only do cell magics - # - user gives %: do both line and cell magics - # - no prefix: do both - # In other words, line magics are skipped if the user gives %% explicitly - # - # We also exclude magics that match any currently visible names: - # https://github.com/ipython/ipython/issues/4877, unless the user has - # typed a %: - # https://github.com/ipython/ipython/issues/10754 - bare_text = text.lstrip(pre) - global_matches = self.global_matches(bare_text) - if not explicit_magic: - def matches(magic): - """ - Filter magics, in particular remove magics that match - a name present in global namespace. - """ - return ( magic.startswith(bare_text) and - magic not in global_matches ) - else: - def matches(magic): - return magic.startswith(bare_text) - - comp = [ pre2+m for m in cell_magics if matches(m)] - if not text.startswith(pre2): - comp += [ pre+m for m in line_magics if matches(m)] - - return comp - - def magic_config_matches(self, text:str) -> List[str]: - """ Match class names and attributes for %config magic """ - texts = text.strip().split() - - if len(texts) > 0 and (texts[0] == 'config' or texts[0] == '%config'): - # get all configuration classes - classes = sorted(set([ c for c in self.shell.configurables - if c.__class__.class_traits(config=True) - ]), key=lambda x: x.__class__.__name__) - classnames = [ c.__class__.__name__ for c in classes ] - - # return all classnames if config or %config is given - if len(texts) == 1: - return classnames - - # match classname - classname_texts = texts[1].split('.') - classname = classname_texts[0] - classname_matches = [ c for c in classnames - if c.startswith(classname) ] - - # return matched classes or the matched class with attributes - if texts[1].find('.') < 0: - return classname_matches - elif len(classname_matches) == 1 and \ - classname_matches[0] == classname: - cls = classes[classnames.index(classname)].__class__ - help = cls.class_get_help() - # strip leading '--' from cl-args: - help = re.sub(re.compile(r'^--', re.MULTILINE), '', help) - return [ attr.split('=')[0] - for attr in help.strip().splitlines() - if attr.startswith(texts[1]) ] - return [] - - def magic_color_matches(self, text:str) -> List[str] : - """ Match color schemes for %colors magic""" - texts = text.split() - if text.endswith(' '): - # .split() strips off the trailing whitespace. Add '' back - # so that: '%colors ' -> ['%colors', ''] - texts.append('') - - if len(texts) == 2 and (texts[0] == 'colors' or texts[0] == '%colors'): - prefix = texts[1] - return [ color for color in InspectColors.keys() - if color.startswith(prefix) ] - return [] - - def _jedi_matches(self, cursor_column:int, cursor_line:int, text:str) -> Iterable[Any]: - """ - Return a list of :any:`jedi.api.Completions` object from a ``text`` and - cursor position. - - Parameters - ---------- - cursor_column : int - column position of the cursor in ``text``, 0-indexed. - cursor_line : int - line position of the cursor in ``text``, 0-indexed - text : str - text to complete - - Notes - ----- - If ``IPCompleter.debug`` is ``True`` may return a :any:`_FakeJediCompletion` - object containing a string with the Jedi debug information attached. - """ - namespaces = [self.namespace] - if self.global_namespace is not None: - namespaces.append(self.global_namespace) - - completion_filter = lambda x:x - offset = cursor_to_position(text, cursor_line, cursor_column) - # filter output if we are completing for object members - if offset: - pre = text[offset-1] - if pre == '.': - if self.omit__names == 2: - completion_filter = lambda c:not c.name.startswith('_') - elif self.omit__names == 1: - completion_filter = lambda c:not (c.name.startswith('__') and c.name.endswith('__')) - elif self.omit__names == 0: - completion_filter = lambda x:x - else: - raise ValueError("Don't understand self.omit__names == {}".format(self.omit__names)) - - interpreter = jedi.Interpreter(text[:offset], namespaces, column=cursor_column, line=cursor_line + 1) - try_jedi = True - - try: - # find the first token in the current tree -- if it is a ' or " then we are in a string - completing_string = False - try: - first_child = next(c for c in interpreter._get_module().tree_node.children if hasattr(c, 'value')) - except StopIteration: - pass - else: - # note the value may be ', ", or it may also be ''' or """, or - # in some cases, """what/you/typed..., but all of these are - # strings. - completing_string = len(first_child.value) > 0 and first_child.value[0] in {"'", '"'} - - # if we are in a string jedi is likely not the right candidate for - # now. Skip it. - try_jedi = not completing_string - except Exception as e: - # many of things can go wrong, we are using private API just don't crash. - if self.debug: - print("Error detecting if completing a non-finished string :", e, '|') - - if not try_jedi: - return [] - try: - return filter(completion_filter, interpreter.completions()) - except Exception as e: - if self.debug: - return [_FakeJediCompletion('Oops Jedi has crashed, please report a bug with the following:\n"""\n%s\ns"""' % (e))] - else: - return [] - - def python_matches(self, text:str)->List[str]: - """Match attributes or global python names""" - if "." in text: - try: - matches = self.attr_matches(text) - if text.endswith('.') and self.omit__names: - if self.omit__names == 1: - # true if txt is _not_ a __ name, false otherwise: - no__name = (lambda txt: - re.match(r'.*\.__.*?__',txt) is None) - else: - # true if txt is _not_ a _ name, false otherwise: - no__name = (lambda txt: - re.match(r'\._.*?',txt[txt.rindex('.'):]) is None) - matches = filter(no__name, matches) - except NameError: - # catches <undefined attributes>.<tab> - matches = [] - else: - matches = self.global_matches(text) - return matches - - def _default_arguments_from_docstring(self, doc): - """Parse the first line of docstring for call signature. - - Docstring should be of the form 'min(iterable[, key=func])\n'. - It can also parse cython docstring of the form - 'Minuit.migrad(self, int ncall=10000, resume=True, int nsplit=1)'. - """ - if doc is None: - return [] - - #care only the firstline - line = doc.lstrip().splitlines()[0] - - #p = re.compile(r'^[\w|\s.]+\(([^)]*)\).*') - #'min(iterable[, key=func])\n' -> 'iterable[, key=func]' - sig = self.docstring_sig_re.search(line) - if sig is None: - return [] - # iterable[, key=func]' -> ['iterable[' ,' key=func]'] - sig = sig.groups()[0].split(',') - ret = [] - for s in sig: - #re.compile(r'[\s|\[]*(\w+)(?:\s*=\s*.*)') - ret += self.docstring_kwd_re.findall(s) - return ret - - def _default_arguments(self, obj): - """Return the list of default arguments of obj if it is callable, - or empty list otherwise.""" - call_obj = obj - ret = [] - if inspect.isbuiltin(obj): - pass - elif not (inspect.isfunction(obj) or inspect.ismethod(obj)): - if inspect.isclass(obj): - #for cython embedsignature=True the constructor docstring - #belongs to the object itself not __init__ - ret += self._default_arguments_from_docstring( - getattr(obj, '__doc__', '')) - # for classes, check for __init__,__new__ - call_obj = (getattr(obj, '__init__', None) or - getattr(obj, '__new__', None)) - # for all others, check if they are __call__able - elif hasattr(obj, '__call__'): - call_obj = obj.__call__ - ret += self._default_arguments_from_docstring( - getattr(call_obj, '__doc__', '')) - - _keeps = (inspect.Parameter.KEYWORD_ONLY, - inspect.Parameter.POSITIONAL_OR_KEYWORD) - - try: - sig = inspect.signature(obj) - ret.extend(k for k, v in sig.parameters.items() if - v.kind in _keeps) - except ValueError: - pass - - return list(set(ret)) - - def python_func_kw_matches(self, text): - """Match named parameters (kwargs) of the last open function""" - - if "." in text: # a parameter cannot be dotted - return [] - try: regexp = self.__funcParamsRegex - except AttributeError: - regexp = self.__funcParamsRegex = re.compile(r''' - '.*?(?<!\\)' | # single quoted strings or - ".*?(?<!\\)" | # double quoted strings or - \w+ | # identifier - \S # other characters - ''', re.VERBOSE | re.DOTALL) - # 1. find the nearest identifier that comes before an unclosed - # parenthesis before the cursor - # e.g. for "foo (1+bar(x), pa<cursor>,a=1)", the candidate is "foo" - tokens = regexp.findall(self.text_until_cursor) - iterTokens = reversed(tokens); openPar = 0 - - for token in iterTokens: - if token == ')': - openPar -= 1 - elif token == '(': - openPar += 1 - if openPar > 0: - # found the last unclosed parenthesis - break - else: - return [] - # 2. Concatenate dotted names ("foo.bar" for "foo.bar(x, pa" ) - ids = [] - isId = re.compile(r'\w+$').match - - while True: - try: - ids.append(next(iterTokens)) - if not isId(ids[-1]): - ids.pop(); break - if not next(iterTokens) == '.': - break - except StopIteration: - break - - # Find all named arguments already assigned to, as to avoid suggesting - # them again - usedNamedArgs = set() - par_level = -1 - for token, next_token in zip(tokens, tokens[1:]): - if token == '(': - par_level += 1 - elif token == ')': - par_level -= 1 - - if par_level != 0: - continue - - if next_token != '=': - continue - - usedNamedArgs.add(token) - - argMatches = [] - try: - callableObj = '.'.join(ids[::-1]) - namedArgs = self._default_arguments(eval(callableObj, - self.namespace)) - - # Remove used named arguments from the list, no need to show twice - for namedArg in set(namedArgs) - usedNamedArgs: - if namedArg.startswith(text): - argMatches.append("%s=" %namedArg) - except: - pass - - return argMatches - - @staticmethod - def _get_keys(obj: Any) -> List[Any]: - # 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: - return list(obj.keys()) - except Exception: - return [] - elif _safe_isinstance(obj, 'numpy', 'ndarray') or\ - _safe_isinstance(obj, 'numpy', 'void'): - return obj.dtype.names or [] - return [] - - def dict_key_matches(self, text:str) -> List[str]: - "Match string keys in a dictionary, after e.g. 'foo[' " - - - if self.__dict_key_regexps is not None: - regexps = self.__dict_key_regexps - else: - dict_key_re_fmt = r'''(?x) - ( # match dict-referring expression wrt greedy setting - %s - ) - \[ # open bracket - \s* # and optional whitespace - # Capture any number of str-like objects (e.g. "a", "b", 'c') - ((?:[uUbB]? # string prefix (r not handled) - (?: - '(?:[^']|(?<!\\)\\')*' - | - "(?:[^"]|(?<!\\)\\")*" - ) - \s*,\s* - )*) - ([uUbB]? # string prefix (r not handled) - (?: # unclosed string - '(?:[^']|(?<!\\)\\')* - | - "(?:[^"]|(?<!\\)\\")* - ) - )? - $ - ''' - regexps = self.__dict_key_regexps = { - False: re.compile(dict_key_re_fmt % r''' - # identifiers separated by . - (?!\d)\w+ - (?:\.(?!\d)\w+)* - '''), - True: re.compile(dict_key_re_fmt % ''' - .+ - ''') - } - - match = regexps[self.greedy].search(self.text_until_cursor) - - if match is None: - return [] - - expr, prefix0, prefix = match.groups() - try: - obj = eval(expr, self.namespace) - except Exception: - try: - obj = eval(expr, self.global_namespace) - except Exception: - return [] - - keys = self._get_keys(obj) - if not keys: - return keys - - extra_prefix = eval(prefix0) if prefix0 != '' else None - - closing_quote, token_offset, matches = match_dict_keys(keys, prefix, self.splitter.delims, extra_prefix=extra_prefix) - if not matches: - return matches - - # get the cursor position of - # - the text being completed - # - the start of the key text - # - the start of the completion - text_start = len(self.text_until_cursor) - len(text) - if prefix: - key_start = match.start(3) - completion_start = key_start + token_offset - else: - key_start = completion_start = match.end() - - # grab the leading prefix, to make sure all completions start with `text` - if text_start > key_start: - leading = '' - else: - leading = text[text_start:completion_start] - - # the index of the `[` character - bracket_idx = match.end(1) - - # append closing quote and bracket as appropriate - # this is *not* appropriate if the opening quote or bracket is outside - # the text given to this method - suf = '' - continuation = self.line_buffer[len(self.text_until_cursor):] - if key_start > text_start and closing_quote: - # quotes were opened inside text, maybe close them - if continuation.startswith(closing_quote): - continuation = continuation[len(closing_quote):] - else: - suf += closing_quote - if bracket_idx > text_start: - # brackets were opened inside text, maybe close them - if not continuation.startswith(']'): - suf += ']' - - return [leading + k + suf for k in matches] - - @staticmethod - def unicode_name_matches(text:str) -> Tuple[str, List[str]] : - """Match Latex-like syntax for unicode characters base - on the name of the character. - - This does ``\\GREEK SMALL LETTER ETA`` -> ``η`` - - Works only on valid python 3 identifier, or on combining characters that - will combine to form a valid identifier. - """ - slashpos = text.rfind('\\') - if slashpos > -1: - s = text[slashpos+1:] - try : - unic = unicodedata.lookup(s) - # allow combining chars - if ('a'+unic).isidentifier(): - return '\\'+s,[unic] - except KeyError: - pass - return '', [] - - - def latex_matches(self, text:str) -> Tuple[str, Sequence[str]]: - """Match Latex syntax for unicode characters. - - This does both ``\\alp`` -> ``\\alpha`` and ``\\alpha`` -> ``α`` - """ - slashpos = text.rfind('\\') - if slashpos > -1: - s = text[slashpos:] - if s in latex_symbols: - # Try to complete a full latex symbol to unicode - # \\alpha -> α - return s, [latex_symbols[s]] - else: - # If a user has partially typed a latex symbol, give them - # a full list of options \al -> [\aleph, \alpha] - matches = [k for k in latex_symbols if k.startswith(s)] - if matches: - return s, matches - return '', () - - def dispatch_custom_completer(self, text): - if not self.custom_completers: - return - - line = self.line_buffer - if not line.strip(): - return None - - # Create a little structure to pass all the relevant information about - # the current completion to any custom completer. - event = SimpleNamespace() - event.line = line - event.symbol = text - cmd = line.split(None,1)[0] - event.command = cmd - event.text_until_cursor = self.text_until_cursor - - # for foo etc, try also to find completer for %foo - if not cmd.startswith(self.magic_escape): - try_magic = self.custom_completers.s_matches( - self.magic_escape + cmd) - else: - try_magic = [] - - for c in itertools.chain(self.custom_completers.s_matches(cmd), - try_magic, - self.custom_completers.flat_matches(self.text_until_cursor)): - try: - res = c(event) - if res: - # first, try case sensitive match - withcase = [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 [r for r in res if r.lower().startswith(text_low)] - except TryNext: - pass - except KeyboardInterrupt: - """ - If custom completer take too long, - let keyboard interrupt abort and return nothing. - """ - break - - return None - - def completions(self, text: str, offset: int)->Iterator[Completion]: - """ - Returns an iterator over the possible completions - - .. warning:: - - Unstable - - This function is unstable, API may change without warning. - It will also raise unless use in proper context manager. - - Parameters - ---------- - text : str - Full text of the current input, multi line string. - offset : int - Integer representing the position of the cursor in ``text``. Offset - is 0-based indexed. - - Yields - ------ - Completion - - Notes - ----- - The cursor on a text can either be seen as being "in between" - characters or "On" a character depending on the interface visible to - the user. For consistency the cursor being on "in between" characters X - and Y is equivalent to the cursor being "on" character Y, that is to say - the character the cursor is on is considered as being after the cursor. - - Combining characters may span more that one position in the - text. - - .. note:: - - If ``IPCompleter.debug`` is :any:`True` will yield a ``--jedi/ipython--`` - fake Completion token to distinguish completion returned by Jedi - and usual IPython completion. - - .. note:: - - Completions are not completely deduplicated yet. If identical - completions are coming from different sources this function does not - ensure that each completion object will only be present once. - """ - warnings.warn("_complete is a provisional API (as of IPython 6.0). " - "It may change without warnings. " - "Use in corresponding context manager.", - category=ProvisionalCompleterWarning, stacklevel=2) - - seen = set() - profiler:Optional[cProfile.Profile] - try: - if self.profile_completions: - import cProfile - profiler = cProfile.Profile() - profiler.enable() - else: - profiler = None - - for c in self._completions(text, offset, _timeout=self.jedi_compute_type_timeout/1000): - if c and (c in seen): - continue - yield c - seen.add(c) - except KeyboardInterrupt: - """if completions take too long and users send keyboard interrupt, - do not crash and return ASAP. """ - pass - finally: - if profiler is not None: - profiler.disable() - ensure_dir_exists(self.profiler_output_dir) - output_path = os.path.join(self.profiler_output_dir, str(uuid.uuid4())) - print("Writing profiler output to", output_path) - profiler.dump_stats(output_path) - - def _completions(self, full_text: str, offset: int, *, _timeout) -> Iterator[Completion]: - """ - Core completion module.Same signature as :any:`completions`, with the - extra `timeout` parameter (in seconds). - - Computing jedi's completion ``.type`` can be quite expensive (it is a - lazy property) and can require some warm-up, more warm up than just - computing the ``name`` of a completion. The warm-up can be : - - - Long warm-up the first time a module is encountered after - install/update: actually build parse/inference tree. - - - first time the module is encountered in a session: load tree from - disk. - - We don't want to block completions for tens of seconds so we give the - completer a "budget" of ``_timeout`` seconds per invocation to compute - completions types, the completions that have not yet been computed will - be marked as "unknown" an will have a chance to be computed next round - are things get cached. - - Keep in mind that Jedi is not the only thing treating the completion so - keep the timeout short-ish as if we take more than 0.3 second we still - have lots of processing to do. - - """ - deadline = time.monotonic() + _timeout - - - before = full_text[:offset] - cursor_line, cursor_column = position_to_cursor(full_text, offset) - - matched_text, matches, matches_origin, jedi_matches = self._complete( - full_text=full_text, cursor_line=cursor_line, cursor_pos=cursor_column) - - iter_jm = iter(jedi_matches) - if _timeout: - for jm in iter_jm: - try: - type_ = jm.type - except Exception: - if self.debug: - print("Error in Jedi getting type of ", jm) - type_ = None - delta = len(jm.name_with_symbols) - len(jm.complete) - if type_ == 'function': - signature = _make_signature(jm) - else: - signature = '' - yield Completion(start=offset - delta, - end=offset, - text=jm.name_with_symbols, - type=type_, - signature=signature, - _origin='jedi') - - if time.monotonic() > deadline: - break - - for jm in iter_jm: - delta = len(jm.name_with_symbols) - len(jm.complete) - yield Completion(start=offset - delta, - end=offset, - text=jm.name_with_symbols, - type='<unknown>', # don't compute type for speed - _origin='jedi', - signature='') - - - start_offset = before.rfind(matched_text) - - # TODO: - # Suppress this, right now just for debug. - if jedi_matches and matches and self.debug: - yield Completion(start=start_offset, end=offset, text='--jedi/ipython--', - _origin='debug', type='none', signature='') - - # I'm unsure if this is always true, so let's assert and see if it - # crash - assert before.endswith(matched_text) - for m, t in zip(matches, matches_origin): - yield Completion(start=start_offset, end=offset, text=m, _origin=t, signature='', type='<unknown>') - - - def complete(self, text=None, line_buffer=None, cursor_pos=None) -> Tuple[str, Sequence[str]]: - """Find completions for the given text and line context. - - Note that both the text and the line_buffer are optional, but at least - one of them must be given. - - Parameters - ---------- - text : string, optional - Text to perform the completion on. If not given, the line buffer - is split using the instance's CompletionSplitter object. - line_buffer : string, optional - If not given, the completer attempts to obtain the current line - buffer via readline. This keyword allows clients which are - requesting for text completions in non-readline contexts to inform - the completer of the entire text. - cursor_pos : int, optional - Index of the cursor in the full line buffer. Should be provided by - remote frontends where kernel has no access to frontend state. - - Returns - ------- - Tuple of two items: - text : str - Text that was actually used in the completion. - matches : list - A list of completion matches. - - Notes - ----- - This API is likely to be deprecated and replaced by - :any:`IPCompleter.completions` in the future. - - """ - warnings.warn('`Completer.complete` is pending deprecation since ' - 'IPython 6.0 and will be replaced by `Completer.completions`.', - PendingDeprecationWarning) - # potential todo, FOLD the 3rd throw away argument of _complete - # into the first 2 one. - return self._complete(line_buffer=line_buffer, cursor_pos=cursor_pos, text=text, cursor_line=0)[:2] - - def _complete(self, *, cursor_line, cursor_pos, line_buffer=None, text=None, - full_text=None) -> _CompleteResult: - """ - Like complete but can also returns raw jedi completions as well as the - origin of the completion text. This could (and should) be made much - cleaner but that will be simpler once we drop the old (and stateful) - :any:`complete` API. - - With current provisional API, cursor_pos act both (depending on the - caller) as the offset in the ``text`` or ``line_buffer``, or as the - ``column`` when passing multiline strings this could/should be renamed - but would add extra noise. - - Parameters - ---------- - cursor_line - Index of the line the cursor is on. 0 indexed. - cursor_pos - Position of the cursor in the current line/line_buffer/text. 0 - indexed. - line_buffer : optional, str - The current line the cursor is in, this is mostly due to legacy - reason that readline could only give a us the single current line. - Prefer `full_text`. - text : str - The current "token" the cursor is in, mostly also for historical - reasons. as the completer would trigger only after the current line - was parsed. - full_text : str - Full text of the current cell. - - Returns - ------- - A tuple of N elements which are (likely): - matched_text: ? the text that the complete matched - matches: list of completions ? - matches_origin: ? list same length as matches, and where each completion came from - jedi_matches: list of Jedi matches, have it's own structure. - """ - - - # if the cursor position isn't given, the only sane assumption we can - # make is that it's at the end of the line (the common case) - if cursor_pos is None: - cursor_pos = len(line_buffer) if text is None else len(text) - - if self.use_main_ns: - self.namespace = __main__.__dict__ - - # if text is either None or an empty string, rely on the line buffer - if (not line_buffer) and full_text: - line_buffer = full_text.split('\n')[cursor_line] - if not text: # issue #11508: check line_buffer before calling split_line - text = self.splitter.split_line(line_buffer, cursor_pos) if line_buffer else '' - - if self.backslash_combining_completions: - # allow deactivation of these on windows. - base_text = text if not line_buffer else line_buffer[:cursor_pos] - - for meth in (self.latex_matches, - self.unicode_name_matches, - back_latex_name_matches, - back_unicode_name_matches, - self.fwd_unicode_match): - name_text, name_matches = meth(base_text) - if name_text: - return _CompleteResult(name_text, name_matches[:MATCHES_LIMIT], \ - [meth.__qualname__]*min(len(name_matches), MATCHES_LIMIT), ()) - - - # If no line buffer is given, assume the input text is all there was - if line_buffer is None: - line_buffer = text - - self.line_buffer = line_buffer - self.text_until_cursor = self.line_buffer[:cursor_pos] - - # Do magic arg matches - for matcher in self.magic_arg_matchers: - matches = list(matcher(line_buffer))[:MATCHES_LIMIT] - if matches: - origins = [matcher.__qualname__] * len(matches) - return _CompleteResult(text, matches, origins, ()) - - # Start with a clean slate of completions - matches = [] - - # FIXME: we should extend our api to return a dict with completions for - # different types of objects. The rlcomplete() method could then - # simply collapse the dict into a list for readline, but we'd have - # richer completion semantics in other environments. - is_magic_prefix = len(text) > 0 and text[0] == "%" - completions: Iterable[Any] = [] - if self.use_jedi and not is_magic_prefix: - if not full_text: - full_text = line_buffer - completions = self._jedi_matches( - cursor_pos, cursor_line, full_text) - - if self.merge_completions: - matches = [] - for matcher in self.matchers: - try: - matches.extend([(m, matcher.__qualname__) - for m in matcher(text)]) - except: - # Show the ugly traceback if the matcher causes an - # exception, but do NOT crash the kernel! - sys.excepthook(*sys.exc_info()) - else: - for matcher in self.matchers: - matches = [(m, matcher.__qualname__) - for m in matcher(text)] - if matches: - break - - seen = set() - filtered_matches = set() - for m in matches: - t, c = m - if t not in seen: - filtered_matches.add(m) - seen.add(t) - - _filtered_matches = sorted(filtered_matches, key=lambda x: completions_sorting_key(x[0])) - - custom_res = [(m, 'custom') for m in self.dispatch_custom_completer(text) or []] - - _filtered_matches = custom_res or _filtered_matches - - _filtered_matches = _filtered_matches[:MATCHES_LIMIT] - _matches = [m[0] for m in _filtered_matches] - origins = [m[1] for m in _filtered_matches] - - self.matches = _matches - - return _CompleteResult(text, _matches, origins, completions) - - def fwd_unicode_match(self, text:str) -> Tuple[str, Sequence[str]]: - """ - Forward match a string starting with a backslash with a list of - potential Unicode completions. - - Will compute list list of Unicode character names on first call and cache it. - - Returns - ------- - At tuple with: - - matched text (empty if no matches) - - list of potential completions, empty tuple otherwise) - """ - # TODO: self.unicode_names is here a list we traverse each time with ~100k elements. - # We could do a faster match using a Trie. - - # Using pygtrie the following seem to work: - - # s = PrefixSet() - - # for c in range(0,0x10FFFF + 1): - # try: - # s.add(unicodedata.name(chr(c))) - # except ValueError: - # pass - # [''.join(k) for k in s.iter(prefix)] - - # But need to be timed and adds an extra dependency. - - slashpos = text.rfind('\\') - # if text starts with slash - if slashpos > -1: - # PERF: It's important that we don't access self._unicode_names - # until we're inside this if-block. _unicode_names is lazily - # initialized, and it takes a user-noticeable amount of time to - # initialize it, so we don't want to initialize it unless we're - # actually going to use it. - s = text[slashpos + 1 :] - sup = s.upper() - candidates = [x for x in self.unicode_names if x.startswith(sup)] - if candidates: - return s, candidates - candidates = [x for x in self.unicode_names if sup in x] - if candidates: - return s, candidates - splitsup = sup.split(" ") - candidates = [ - x for x in self.unicode_names if all(u in x for u in splitsup) - ] - if candidates: - return s, candidates - - return "", () - - # if text does not start with slash - else: - return '', () - - @property - def unicode_names(self) -> List[str]: - """List of names of unicode code points that can be completed. - - The list is lazily initialized on first access. - """ - if self._unicode_names is None: - names = [] - for c in range(0,0x10FFFF + 1): - try: - names.append(unicodedata.name(chr(c))) - except ValueError: - pass - self._unicode_names = _unicode_name_compute(_UNICODE_RANGES) - - return self._unicode_names - -def _unicode_name_compute(ranges:List[Tuple[int,int]]) -> List[str]: - names = [] - for start,stop in ranges: - for c in range(start, stop) : - try: - names.append(unicodedata.name(chr(c))) - except ValueError: - pass - return names diff --git a/contrib/python/ipython/py3/IPython/core/completerlib.py b/contrib/python/ipython/py3/IPython/core/completerlib.py deleted file mode 100644 index 65efa42254..0000000000 --- a/contrib/python/ipython/py3/IPython/core/completerlib.py +++ /dev/null @@ -1,418 +0,0 @@ -# encoding: utf-8 -"""Implementations for various useful completers. - -These are all loaded by default by IPython. -""" -#----------------------------------------------------------------------------- -# Copyright (C) 2010-2011 The IPython Development Team. -# -# Distributed under the terms of the BSD License. -# -# The full license is in the file COPYING.txt, distributed with this software. -#----------------------------------------------------------------------------- - -#----------------------------------------------------------------------------- -# Imports -#----------------------------------------------------------------------------- - -# Stdlib imports -import glob -import inspect -import itertools -import os -import re -import sys -from importlib import import_module -from importlib.machinery import all_suffixes - - -# Third-party imports -from time import time -from zipimport import zipimporter - -# Our own imports -from .completer import expand_user, compress_user -from .error import TryNext -from ..utils._process_common import arg_split - -# FIXME: this should be pulled in with the right call via the component system -from IPython import get_ipython - -from typing import List - -from __res import importer - -#----------------------------------------------------------------------------- -# Globals and constants -#----------------------------------------------------------------------------- -_suffixes = all_suffixes() - -# Time in seconds after which the rootmodules will be stored permanently in the -# ipython ip.db database (kept in the user's .ipython dir). -TIMEOUT_STORAGE = 2 - -# Time in seconds after which we give up -TIMEOUT_GIVEUP = 20 - -# Regular expression for the python import statement -import_re = re.compile(r'(?P<name>[^\W\d]\w*?)' - r'(?P<package>[/\\]__init__)?' - r'(?P<suffix>%s)$' % - r'|'.join(re.escape(s) for s in _suffixes)) - -# RE for the ipython %run command (python + ipython scripts) -magic_run_re = re.compile(r'.*(\.ipy|\.ipynb|\.py[w]?)$') - -#----------------------------------------------------------------------------- -# Local utilities -#----------------------------------------------------------------------------- - -arcadia_rootmodules_cache = None -arcadia_modules_cache = None - - -def arcadia_init_cache(): - global arcadia_rootmodules_cache, arcadia_modules_cache - arcadia_rootmodules_cache = set() - arcadia_modules_cache = {} - - all_modules = itertools.chain( - sys.builtin_module_names, - importer.memory - ) - - for name in all_modules: - path = name.split('.') - arcadia_rootmodules_cache.add(path[0]) - - prefix = path[0] - for element in path[1:]: - if element == '__init__': - continue - - arcadia_modules_cache.setdefault(prefix, set()).add(element) - prefix += '.' + element - - arcadia_rootmodules_cache = sorted(arcadia_rootmodules_cache) - arcadia_modules_cache = {k: sorted(v) for k, v in arcadia_modules_cache.items()} - - -def arcadia_module_list(mod): - if arcadia_modules_cache is None: - arcadia_init_cache() - - return arcadia_modules_cache.get(mod, ()) - - -def arcadia_get_root_modules(): - if arcadia_rootmodules_cache is None: - arcadia_init_cache() - - return arcadia_rootmodules_cache - - -def module_list(path): - """ - Return the list containing the names of the modules available in the given - folder. - """ - # sys.path has the cwd as an empty string, but isdir/listdir need it as '.' - if path == '': - path = '.' - - # A few local constants to be used in loops below - pjoin = os.path.join - - if os.path.isdir(path): - # Build a list of all files in the directory and all files - # in its subdirectories. For performance reasons, do not - # recurse more than one level into subdirectories. - files = [] - for root, dirs, nondirs in os.walk(path, followlinks=True): - subdir = root[len(path)+1:] - if subdir: - files.extend(pjoin(subdir, f) for f in nondirs) - dirs[:] = [] # Do not recurse into additional subdirectories. - else: - files.extend(nondirs) - - else: - try: - files = list(zipimporter(path)._files.keys()) - except: - files = [] - - # Build a list of modules which match the import_re regex. - modules = [] - for f in files: - m = import_re.match(f) - if m: - modules.append(m.group('name')) - return list(set(modules)) - - -def get_root_modules(): - """ - Returns a list containing the names of all the modules available in the - folders of the pythonpath. - - ip.db['rootmodules_cache'] maps sys.path entries to list of modules. - """ - ip = get_ipython() - if ip is None: - # No global shell instance to store cached list of modules. - # Don't try to scan for modules every time. - return list(sys.builtin_module_names) - - rootmodules_cache = ip.db.get('rootmodules_cache', {}) - rootmodules = list(sys.builtin_module_names) - start_time = time() - store = False - for path in sys.path: - try: - modules = rootmodules_cache[path] - except KeyError: - modules = module_list(path) - try: - modules.remove('__init__') - except ValueError: - pass - if path not in ('', '.'): # cwd modules should not be cached - rootmodules_cache[path] = modules - if time() - start_time > TIMEOUT_STORAGE and not store: - store = True - print("\nCaching the list of root modules, please wait!") - print("(This will only be done once - type '%rehashx' to " - "reset cache!)\n") - sys.stdout.flush() - if time() - start_time > TIMEOUT_GIVEUP: - print("This is taking too long, we give up.\n") - return [] - rootmodules.extend(modules) - if store: - ip.db['rootmodules_cache'] = rootmodules_cache - rootmodules = list(set(rootmodules)) - return rootmodules - - -def is_importable(module, attr, only_modules): - if only_modules: - return inspect.ismodule(getattr(module, attr)) - else: - return not(attr[:2] == '__' and attr[-2:] == '__') - -def is_possible_submodule(module, attr): - try: - obj = getattr(module, attr) - except AttributeError: - # Is possilby an unimported submodule - return True - except TypeError: - # https://github.com/ipython/ipython/issues/9678 - return False - return inspect.ismodule(obj) - - -def try_import(mod: str, only_modules=False) -> List[str]: - """ - Try to import given module and return list of potential completions. - """ - mod = mod.rstrip('.') - try: - m = import_module(mod) - except: - return [] - - filename = getattr(m, '__file__', '') - m_is_init = '__init__' in (filename or '') or filename == mod - - completions = [] - if (not hasattr(m, '__file__')) or (not only_modules) or m_is_init: - completions.extend( [attr for attr in dir(m) if - is_importable(m, attr, only_modules)]) - - m_all = getattr(m, "__all__", []) - if only_modules: - completions.extend(attr for attr in m_all if is_possible_submodule(m, attr)) - else: - completions.extend(m_all) - - if m_is_init: - completions.extend(arcadia_module_list(mod)) - completions_set = {c for c in completions if isinstance(c, str)} - completions_set.discard('__init__') - return sorted(completions_set) - - -#----------------------------------------------------------------------------- -# Completion-related functions. -#----------------------------------------------------------------------------- - -def quick_completer(cmd, completions): - r""" Easily create a trivial completer for a command. - - Takes either a list of completions, or all completions in string (that will - be split on whitespace). - - Example:: - - [d:\ipython]|1> import ipy_completers - [d:\ipython]|2> ipy_completers.quick_completer('foo', ['bar','baz']) - [d:\ipython]|3> foo b<TAB> - bar baz - [d:\ipython]|3> foo ba - """ - - if isinstance(completions, str): - completions = completions.split() - - def do_complete(self, event): - return completions - - get_ipython().set_hook('complete_command',do_complete, str_key = cmd) - -def module_completion(line): - """ - Returns a list containing the completion possibilities for an import line. - - The line looks like this : - 'import xml.d' - 'from xml.dom import' - """ - - words = line.split(' ') - nwords = len(words) - - # from whatever <tab> -> 'import ' - if nwords == 3 and words[0] == 'from': - return ['import '] - - # 'from xy<tab>' or 'import xy<tab>' - if nwords < 3 and (words[0] in {'%aimport', 'import', 'from'}) : - if nwords == 1: - return arcadia_get_root_modules() - mod = words[1].split('.') - if len(mod) < 2: - return arcadia_get_root_modules() - completion_list = try_import('.'.join(mod[:-1]), True) - return ['.'.join(mod[:-1] + [el]) for el in completion_list] - - # 'from xyz import abc<tab>' - if nwords >= 3 and words[0] == 'from': - mod = words[1] - return try_import(mod) - -#----------------------------------------------------------------------------- -# Completers -#----------------------------------------------------------------------------- -# These all have the func(self, event) signature to be used as custom -# completers - -def module_completer(self,event): - """Give completions after user has typed 'import ...' or 'from ...'""" - - # This works in all versions of python. While 2.5 has - # pkgutil.walk_packages(), that particular routine is fairly dangerous, - # since it imports *EVERYTHING* on sys.path. That is: a) very slow b) full - # of possibly problematic side effects. - # This search the folders in the sys.path for available modules. - - return module_completion(event.line) - -# FIXME: there's a lot of logic common to the run, cd and builtin file -# completers, that is currently reimplemented in each. - -def magic_run_completer(self, event): - """Complete files that end in .py or .ipy or .ipynb for the %run command. - """ - comps = arg_split(event.line, strict=False) - # relpath should be the current token that we need to complete. - if (len(comps) > 1) and (not event.line.endswith(' ')): - relpath = comps[-1].strip("'\"") - else: - relpath = '' - - #print("\nev=", event) # dbg - #print("rp=", relpath) # dbg - #print('comps=', comps) # dbg - - lglob = glob.glob - isdir = os.path.isdir - relpath, tilde_expand, tilde_val = expand_user(relpath) - - # Find if the user has already typed the first filename, after which we - # should complete on all files, since after the first one other files may - # be arguments to the input script. - - if any(magic_run_re.match(c) for c in comps): - matches = [f.replace('\\','/') + ('/' if isdir(f) else '') - for f in lglob(relpath+'*')] - else: - dirs = [f.replace('\\','/') + "/" for f in lglob(relpath+'*') if isdir(f)] - pys = [f.replace('\\','/') - for f in lglob(relpath+'*.py') + lglob(relpath+'*.ipy') + - lglob(relpath+'*.ipynb') + lglob(relpath + '*.pyw')] - - matches = dirs + pys - - #print('run comp:', dirs+pys) # dbg - return [compress_user(p, tilde_expand, tilde_val) for p in matches] - - -def cd_completer(self, event): - """Completer function for cd, which only returns directories.""" - ip = get_ipython() - relpath = event.symbol - - #print(event) # dbg - if event.line.endswith('-b') or ' -b ' in event.line: - # return only bookmark completions - bkms = self.db.get('bookmarks', None) - if bkms: - return bkms.keys() - else: - return [] - - if event.symbol == '-': - width_dh = str(len(str(len(ip.user_ns['_dh']) + 1))) - # jump in directory history by number - fmt = '-%0' + width_dh +'d [%s]' - ents = [ fmt % (i,s) for i,s in enumerate(ip.user_ns['_dh'])] - if len(ents) > 1: - return ents - return [] - - if event.symbol.startswith('--'): - return ["--" + os.path.basename(d) for d in ip.user_ns['_dh']] - - # Expand ~ in path and normalize directory separators. - relpath, tilde_expand, tilde_val = expand_user(relpath) - relpath = relpath.replace('\\','/') - - found = [] - for d in [f.replace('\\','/') + '/' for f in glob.glob(relpath+'*') - if os.path.isdir(f)]: - if ' ' in d: - # we don't want to deal with any of that, complex code - # for this is elsewhere - raise TryNext - - found.append(d) - - if not found: - if os.path.isdir(relpath): - return [compress_user(relpath, tilde_expand, tilde_val)] - - # if no completions so far, try bookmarks - bks = self.db.get('bookmarks',{}) - bkmatches = [s for s in bks if s.startswith(event.symbol)] - if bkmatches: - return bkmatches - - raise TryNext - - return [compress_user(p, tilde_expand, tilde_val) for p in found] - -def reset_completer(self, event): - "A completer for %reset magic" - return '-f -s in out array dhist'.split() diff --git a/contrib/python/ipython/py3/IPython/core/crashhandler.py b/contrib/python/ipython/py3/IPython/core/crashhandler.py deleted file mode 100644 index 4af39361e8..0000000000 --- a/contrib/python/ipython/py3/IPython/core/crashhandler.py +++ /dev/null @@ -1,237 +0,0 @@ -# encoding: utf-8 -"""sys.excepthook for IPython itself, leaves a detailed report on disk. - -Authors: - -* Fernando Perez -* Brian E. Granger -""" - -#----------------------------------------------------------------------------- -# Copyright (C) 2001-2007 Fernando Perez. <fperez@colorado.edu> -# Copyright (C) 2008-2011 The IPython Development Team -# -# Distributed under the terms of the BSD License. The full license is in -# the file COPYING, distributed as part of this software. -#----------------------------------------------------------------------------- - -#----------------------------------------------------------------------------- -# Imports -#----------------------------------------------------------------------------- - -import os -import sys -import traceback -from pprint import pformat -from pathlib import Path - -from IPython.core import ultratb -from IPython.core.release import author_email -from IPython.utils.sysinfo import sys_info -from IPython.utils.py3compat import input - -from IPython.core.release import __version__ as version - -from typing import Optional - -#----------------------------------------------------------------------------- -# Code -#----------------------------------------------------------------------------- - -# Template for the user message. -_default_message_template = """\ -Oops, {app_name} crashed. We do our best to make it stable, but... - -A crash report was automatically generated with the following information: - - A verbatim copy of the crash traceback. - - A copy of your input history during this session. - - Data on your current {app_name} configuration. - -It was left in the file named: -\t'{crash_report_fname}' -If you can email this file to the developers, the information in it will help -them in understanding and correcting the problem. - -You can mail it to: {contact_name} at {contact_email} -with the subject '{app_name} Crash Report'. - -If you want to do it now, the following command will work (under Unix): -mail -s '{app_name} Crash Report' {contact_email} < {crash_report_fname} - -In your email, please also include information about: -- The operating system under which the crash happened: Linux, macOS, Windows, - other, and which exact version (for example: Ubuntu 16.04.3, macOS 10.13.2, - Windows 10 Pro), and whether it is 32-bit or 64-bit; -- How {app_name} was installed: using pip or conda, from GitHub, as part of - a Docker container, or other, providing more detail if possible; -- How to reproduce the crash: what exact sequence of instructions can one - input to get the same crash? Ideally, find a minimal yet complete sequence - of instructions that yields the crash. - -To ensure accurate tracking of this issue, please file a report about it at: -{bug_tracker} -""" - -_lite_message_template = """ -If you suspect this is an IPython {version} bug, please report it at: - https://github.com/ipython/ipython/issues -or send an email to the mailing list at {email} - -You can print a more detailed traceback right now with "%tb", or use "%debug" -to interactively debug it. - -Extra-detailed tracebacks for bug-reporting purposes can be enabled via: - {config}Application.verbose_crash=True -""" - - -class CrashHandler(object): - """Customizable crash handlers for IPython applications. - - Instances of this class provide a :meth:`__call__` method which can be - used as a ``sys.excepthook``. The :meth:`__call__` signature is:: - - def __call__(self, etype, evalue, etb) - """ - - message_template = _default_message_template - section_sep = '\n\n'+'*'*75+'\n\n' - - def __init__( - self, - app, - contact_name: Optional[str] = None, - contact_email: Optional[str] = None, - bug_tracker: Optional[str] = None, - show_crash_traceback: bool = True, - call_pdb: bool = False, - ): - """Create a new crash handler - - Parameters - ---------- - app : Application - A running :class:`Application` instance, which will be queried at - crash time for internal information. - contact_name : str - A string with the name of the person to contact. - contact_email : str - A string with the email address of the contact. - bug_tracker : str - A string with the URL for your project's bug tracker. - show_crash_traceback : bool - If false, don't print the crash traceback on stderr, only generate - the on-disk report - call_pdb - Whether to call pdb on crash - - Attributes - ---------- - These instances contain some non-argument attributes which allow for - further customization of the crash handler's behavior. Please see the - source for further details. - - """ - self.crash_report_fname = "Crash_report_%s.txt" % app.name - self.app = app - self.call_pdb = call_pdb - #self.call_pdb = True # dbg - self.show_crash_traceback = show_crash_traceback - self.info = dict(app_name = app.name, - contact_name = contact_name, - contact_email = contact_email, - bug_tracker = bug_tracker, - crash_report_fname = self.crash_report_fname) - - - def __call__(self, etype, evalue, etb): - """Handle an exception, call for compatible with sys.excepthook""" - - # do not allow the crash handler to be called twice without reinstalling it - # this prevents unlikely errors in the crash handling from entering an - # infinite loop. - sys.excepthook = sys.__excepthook__ - - # Report tracebacks shouldn't use color in general (safer for users) - color_scheme = 'NoColor' - - # Use this ONLY for developer debugging (keep commented out for release) - #color_scheme = 'Linux' # dbg - try: - rptdir = self.app.ipython_dir - except: - rptdir = Path.cwd() - if rptdir is None or not Path.is_dir(rptdir): - rptdir = Path.cwd() - report_name = rptdir / self.crash_report_fname - # write the report filename into the instance dict so it can get - # properly expanded out in the user message template - self.crash_report_fname = report_name - self.info['crash_report_fname'] = report_name - TBhandler = ultratb.VerboseTB( - color_scheme=color_scheme, - long_header=1, - call_pdb=self.call_pdb, - ) - if self.call_pdb: - TBhandler(etype,evalue,etb) - return - else: - traceback = TBhandler.text(etype,evalue,etb,context=31) - - # print traceback to screen - if self.show_crash_traceback: - print(traceback, file=sys.stderr) - - # and generate a complete report on disk - try: - report = open(report_name, "w", encoding="utf-8") - except: - print('Could not create crash report on disk.', file=sys.stderr) - return - - with report: - # Inform user on stderr of what happened - print('\n'+'*'*70+'\n', file=sys.stderr) - print(self.message_template.format(**self.info), file=sys.stderr) - - # Construct report on disk - report.write(self.make_report(traceback)) - - input("Hit <Enter> to quit (your terminal may close):") - - def make_report(self,traceback): - """Return a string containing a crash report.""" - - sec_sep = self.section_sep - - report = ['*'*75+'\n\n'+'IPython post-mortem report\n\n'] - rpt_add = report.append - rpt_add(sys_info()) - - try: - config = pformat(self.app.config) - rpt_add(sec_sep) - rpt_add('Application name: %s\n\n' % self.app_name) - rpt_add('Current user configuration structure:\n\n') - rpt_add(config) - except: - pass - rpt_add(sec_sep+'Crash traceback:\n\n' + traceback) - - return ''.join(report) - - -def crash_handler_lite(etype, evalue, tb): - """a light excepthook, adding a small message to the usual traceback""" - traceback.print_exception(etype, evalue, tb) - - from IPython.core.interactiveshell import InteractiveShell - if InteractiveShell.initialized(): - # we are in a Shell environment, give %magic example - config = "%config " - else: - # we are not in a shell, show generic config - config = "c." - print(_lite_message_template.format(email=author_email, config=config, version=version), file=sys.stderr) - diff --git a/contrib/python/ipython/py3/IPython/core/debugger.py b/contrib/python/ipython/py3/IPython/core/debugger.py deleted file mode 100644 index ba12e3eac3..0000000000 --- a/contrib/python/ipython/py3/IPython/core/debugger.py +++ /dev/null @@ -1,999 +0,0 @@ -# -*- coding: utf-8 -*- -""" -Pdb debugger class. - - -This is an extension to PDB which adds a number of new features. -Note that there is also the `IPython.terminal.debugger` class which provides UI -improvements. - -We also strongly recommend to use this via the `ipdb` package, which provides -extra configuration options. - -Among other things, this subclass of PDB: - - supports many IPython magics like pdef/psource - - hide frames in tracebacks based on `__tracebackhide__` - - allows to skip frames based on `__debuggerskip__` - -The skipping and hiding frames are configurable via the `skip_predicates` -command. - -By default, frames from readonly files will be hidden, frames containing -``__tracebackhide__=True`` will be hidden. - -Frames containing ``__debuggerskip__`` will be stepped over, frames who's parent -frames value of ``__debuggerskip__`` is ``True`` will be skipped. - - >>> def helpers_helper(): - ... pass - ... - ... def helper_1(): - ... print("don't step in me") - ... helpers_helpers() # will be stepped over unless breakpoint set. - ... - ... - ... def helper_2(): - ... print("in me neither") - ... - -One can define a decorator that wraps a function between the two helpers: - - >>> def pdb_skipped_decorator(function): - ... - ... - ... def wrapped_fn(*args, **kwargs): - ... __debuggerskip__ = True - ... helper_1() - ... __debuggerskip__ = False - ... result = function(*args, **kwargs) - ... __debuggerskip__ = True - ... helper_2() - ... # setting __debuggerskip__ to False again is not necessary - ... return result - ... - ... return wrapped_fn - -When decorating a function, ipdb will directly step into ``bar()`` by -default: - - >>> @foo_decorator - ... def bar(x, y): - ... return x * y - - -You can toggle the behavior with - - ipdb> skip_predicates debuggerskip false - -or configure it in your ``.pdbrc`` - - - -License -------- - -Modified from the standard pdb.Pdb class to avoid including readline, so that -the command line completion of other programs which include this isn't -damaged. - -In the future, this class will be expanded with improvements over the standard -pdb. - -The original code in this file is mainly lifted out of cmd.py in Python 2.2, -with minor changes. Licensing should therefore be under the standard Python -terms. For details on the PSF (Python Software Foundation) standard license, -see: - -https://docs.python.org/2/license.html - - -All the changes since then are under the same license as IPython. - -""" - -#***************************************************************************** -# -# This file is licensed under the PSF license. -# -# Copyright (C) 2001 Python Software Foundation, www.python.org -# Copyright (C) 2005-2006 Fernando Perez. <fperez@colorado.edu> -# -# -#***************************************************************************** - -import inspect -import linecache -import sys -import warnings -import re -import os - -from IPython import get_ipython -from IPython.utils import PyColorize -from IPython.utils import coloransi, py3compat -from IPython.core.excolors import exception_colors - -# skip module docstests -__skip_doctest__ = True - -prompt = 'ipdb> ' - -# We have to check this directly from sys.argv, config struct not yet available -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. - -DEBUGGERSKIP = "__debuggerskip__" - - -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. - """ - raise ValueError( - "`BdbQuit_excepthook` is deprecated since version 5.1", - ) - - -def BdbQuit_IPython_excepthook(self, et, ev, tb, tb_offset=None): - raise ValueError( - "`BdbQuit_IPython_excepthook` is deprecated since version 5.1", - DeprecationWarning, stacklevel=2) - - -RGX_EXTRA_INDENT = re.compile(r'(?<=\n)\s+') - - -def strip_indentation(multiline_string): - return RGX_EXTRA_INDENT.sub('', multiline_string) - - -def decorate_fn_with_doc(new_fn, old_fn, additional_text=""): - """Make new_fn have old_fn's doc string. This is particularly useful - for the ``do_...`` commands that hook into the help system. - Adapted from from a comp.lang.python posting - by Duncan Booth.""" - def wrapper(*args, **kw): - return new_fn(*args, **kw) - if old_fn.__doc__: - wrapper.__doc__ = strip_indentation(old_fn.__doc__) + additional_text - return wrapper - - -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()` - - - This debugger can hide and skip frames that are tagged according to some predicates. - See the `skip_predicates` commands. - - """ - - default_predicates = { - "tbhide": True, - "readonly": False, - "ipython_internal": True, - "debuggerskip": True, - } - - def __init__(self, completekey=None, stdin=None, stdout=None, context=5, **kwargs): - """Create a new IPython debugger. - - Parameters - ---------- - completekey : default None - Passed to pdb.Pdb. - stdin : default None - Passed to pdb.Pdb. - stdout : default None - Passed to pdb.Pdb. - context : int - Number of lines of source code context to show when - displaying stacktrace information. - **kwargs - Passed to pdb.Pdb. - - Notes - ----- - The possibilities are python version dependent, see the python - docs for more info. - """ - - # Parent constructor: - try: - self.context = int(context) - if self.context <= 0: - raise ValueError("Context must be a positive integer") - except (TypeError, ValueError) as e: - raise ValueError("Context must be a positive integer") from e - - # `kwargs` ensures full compatibility with stdlib's `pdb.Pdb`. - OldPdb.__init__(self, completekey, stdin, stdout, **kwargs) - - # IPython changes... - self.shell = get_ipython() - - if self.shell is None: - save_main = sys.modules['__main__'] - # No IPython instance running, we must create one - from IPython.terminal.interactiveshell import \ - TerminalInteractiveShell - self.shell = TerminalInteractiveShell.instance() - # needed by any code which calls __import__("__main__") after - # the debugger was entered. See also #9941. - sys.modules["__main__"] = save_main - - - color_scheme = self.shell.colors - - self.aliases = {} - - # Create color table: we copy the default one from the traceback - # module and add a few attributes needed for debugging - self.color_scheme_table = exception_colors() - - # shorthands - C = coloransi.TermColors - cst = self.color_scheme_table - - cst['NoColor'].colors.prompt = C.NoColor - cst['NoColor'].colors.breakpoint_enabled = C.NoColor - cst['NoColor'].colors.breakpoint_disabled = C.NoColor - - cst['Linux'].colors.prompt = C.Green - cst['Linux'].colors.breakpoint_enabled = C.LightRed - cst['Linux'].colors.breakpoint_disabled = C.Red - - cst['LightBG'].colors.prompt = C.Blue - 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 - - # Add a python parser so we can syntax highlight source while - # debugging. - self.parser = PyColorize.Parser(style=color_scheme) - self.set_colors(color_scheme) - - # Set the prompt - the default prompt is '(Pdb)' - self.prompt = prompt - self.skip_hidden = True - self.report_skipped = True - - # list of predicates we use to skip frames - self._predicates = self.default_predicates - - # - def set_colors(self, scheme): - """Shorthand access to the color table scheme selector method.""" - self.color_scheme_table.set_active_scheme(scheme) - self.parser.style = scheme - - def set_trace(self, frame=None): - if frame is None: - frame = sys._getframe().f_back - self.initial_frame = frame - return super().set_trace(frame) - - def _hidden_predicate(self, frame): - """ - Given a frame return whether it it should be hidden or not by IPython. - """ - - if self._predicates["readonly"]: - fname = frame.f_code.co_filename - # we need to check for file existence and interactively define - # function would otherwise appear as RO. - if os.path.isfile(fname) and not os.access(fname, os.W_OK): - return True - - if self._predicates["tbhide"]: - if frame in (self.curframe, getattr(self, "initial_frame", None)): - return False - frame_locals = self._get_frame_locals(frame) - if "__tracebackhide__" not in frame_locals: - return False - return frame_locals["__tracebackhide__"] - return False - - def hidden_frames(self, stack): - """ - Given an index in the stack return whether it should be skipped. - - This is used in up/down and where to skip frames. - """ - # The f_locals dictionary is updated from the actual frame - # locals whenever the .f_locals accessor is called, so we - # avoid calling it here to preserve self.curframe_locals. - # Furthermore, there is no good reason to hide the current frame. - ip_hide = [self._hidden_predicate(s[0]) for s in stack] - ip_start = [i for i, s in enumerate(ip_hide) if s == "__ipython_bottom__"] - if ip_start and self._predicates["ipython_internal"]: - ip_hide = [h if i > ip_start[0] else True for (i, h) in enumerate(ip_hide)] - return ip_hide - - def interaction(self, frame, traceback): - try: - OldPdb.interaction(self, frame, traceback) - except KeyboardInterrupt: - self.stdout.write("\n" + self.shell.get_exception_only()) - - def precmd(self, line): - """Perform useful escapes on the command before it is executed.""" - - if line.endswith("??"): - line = "pinfo2 " + line[:-2] - elif line.endswith("?"): - line = "pinfo " + line[:-1] - - line = super().precmd(line) - - return line - - def new_do_frame(self, arg): - OldPdb.do_frame(self, arg) - - def new_do_quit(self, arg): - - if hasattr(self, 'old_all_completions'): - self.shell.Completer.all_completions = self.old_all_completions - - return OldPdb.do_quit(self, arg) - - do_q = do_quit = decorate_fn_with_doc(new_do_quit, OldPdb.do_quit) - - def new_do_restart(self, arg): - """Restart command. In the context of ipython this is exactly the same - thing as 'quit'.""" - self.msg("Restart doesn't make sense here. Using 'quit' instead.") - return self.do_quit(arg) - - def print_stack_trace(self, context=None): - Colors = self.color_scheme_table.active_colors - ColorsNormal = Colors.Normal - if context is None: - context = self.context - try: - context = int(context) - if context <= 0: - raise ValueError("Context must be a positive integer") - except (TypeError, ValueError) as e: - raise ValueError("Context must be a positive integer") from e - try: - skipped = 0 - for hidden, frame_lineno in zip(self.hidden_frames(self.stack), self.stack): - if hidden and self.skip_hidden: - skipped += 1 - continue - if skipped: - print( - f"{Colors.excName} [... skipping {skipped} hidden frame(s)]{ColorsNormal}\n" - ) - skipped = 0 - self.print_stack_entry(frame_lineno, context=context) - if skipped: - print( - f"{Colors.excName} [... skipping {skipped} hidden frame(s)]{ColorsNormal}\n" - ) - except KeyboardInterrupt: - pass - - def print_stack_entry(self, frame_lineno, prompt_prefix='\n-> ', - context=None): - if context is None: - context = self.context - try: - context = int(context) - if context <= 0: - raise ValueError("Context must be a positive integer") - except (TypeError, ValueError) as e: - raise ValueError("Context must be a positive integer") from e - print(self.format_stack_entry(frame_lineno, '', context), file=self.stdout) - - # vds: >> - frame, lineno = frame_lineno - filename = frame.f_code.co_filename - self.shell.hooks.synchronize_with_editor(filename, lineno, 0) - # vds: << - - def _get_frame_locals(self, frame): - """ " - Accessing f_local of current frame reset the namespace, so we want to avoid - that or the following can happen - - ipdb> foo - "old" - ipdb> foo = "new" - ipdb> foo - "new" - ipdb> where - ipdb> foo - "old" - - So if frame is self.current_frame we instead return self.curframe_locals - - """ - if frame is self.curframe: - return self.curframe_locals - else: - return frame.f_locals - - def format_stack_entry(self, frame_lineno, lprefix=': ', context=None): - if context is None: - context = self.context - try: - context = int(context) - if context <= 0: - print("Context must be a positive integer", file=self.stdout) - except (TypeError, ValueError): - print("Context must be a positive integer", file=self.stdout) - - import reprlib - - ret = [] - - Colors = self.color_scheme_table.active_colors - ColorsNormal = Colors.Normal - tpl_link = "%s%%s%s" % (Colors.filenameEm, ColorsNormal) - tpl_call = "%s%%s%s%%s%s" % (Colors.vName, Colors.valEm, ColorsNormal) - tpl_line = "%%s%s%%s %s%%s" % (Colors.lineno, ColorsNormal) - tpl_line_em = "%%s%s%%s %s%%s%s" % (Colors.linenoEm, Colors.line, ColorsNormal) - - frame, lineno = frame_lineno - - return_value = '' - loc_frame = self._get_frame_locals(frame) - if "__return__" in loc_frame: - rv = loc_frame["__return__"] - # return_value += '->' - return_value += reprlib.repr(rv) + "\n" - ret.append(return_value) - - #s = filename + '(' + `lineno` + ')' - filename = self.canonic(frame.f_code.co_filename) - link = tpl_link % py3compat.cast_unicode(filename) - - if frame.f_code.co_name: - func = frame.f_code.co_name - else: - func = "<lambda>" - - call = "" - if func != "?": - if "__args__" in loc_frame: - args = reprlib.repr(loc_frame["__args__"]) - else: - args = '()' - call = tpl_call % (func, args) - - # The level info should be generated in the same format pdb uses, to - # avoid breaking the pdbtrack functionality of python-mode in *emacs. - if frame is self.curframe: - ret.append('> ') - else: - ret.append(" ") - ret.append("%s(%s)%s\n" % (link, lineno, call)) - - start = lineno - 1 - context//2 - lines = linecache.getlines(filename) - start = min(start, len(lines) - context) - start = max(start, 0) - lines = lines[start : start + context] - - for i, line in enumerate(lines): - show_arrow = start + 1 + i == lineno - linetpl = (frame is self.curframe or show_arrow) and tpl_line_em or tpl_line - ret.append( - self.__format_line( - linetpl, filename, start + 1 + i, line, arrow=show_arrow - ) - ) - return "".join(ret) - - def __format_line(self, tpl_line, filename, lineno, line, arrow=False): - bp_mark = "" - bp_mark_color = "" - - new_line, err = self.parser.format2(line, 'str') - if not err: - line = new_line - - bp = None - if lineno in self.get_file_breaks(filename): - bps = self.get_breaks(filename, lineno) - bp = bps[-1] - - if bp: - Colors = self.color_scheme_table.active_colors - bp_mark = str(bp.number) - bp_mark_color = Colors.breakpoint_enabled - if not bp.enabled: - bp_mark_color = Colors.breakpoint_disabled - - numbers_width = 7 - 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)) - else: - num = '%*s' % (numbers_width - len(bp_mark), str(lineno)) - - return tpl_line % (bp_mark_color + bp_mark, num, line) - - def print_list_lines(self, filename, first, last): - """The printing (as opposed to the parsing part of a 'list' - command.""" - try: - Colors = self.color_scheme_table.active_colors - ColorsNormal = Colors.Normal - tpl_line = '%%s%s%%s %s%%s' % (Colors.lineno, ColorsNormal) - tpl_line_em = '%%s%s%%s %s%%s%s' % (Colors.linenoEm, Colors.line, ColorsNormal) - src = [] - if filename == "<string>" and hasattr(self, "_exec_filename"): - filename = self._exec_filename - - for lineno in range(first, last+1): - line = linecache.getline(filename, lineno) - if not line: - break - - if lineno == self.curframe.f_lineno: - line = self.__format_line( - tpl_line_em, filename, lineno, line, arrow=True - ) - else: - line = self.__format_line( - tpl_line, filename, lineno, line, arrow=False - ) - - src.append(line) - self.lineno = lineno - - print(''.join(src), file=self.stdout) - - except KeyboardInterrupt: - pass - - def do_skip_predicates(self, args): - """ - Turn on/off individual predicates as to whether a frame should be hidden/skip. - - The global option to skip (or not) hidden frames is set with skip_hidden - - To change the value of a predicate - - skip_predicates key [true|false] - - Call without arguments to see the current values. - - To permanently change the value of an option add the corresponding - command to your ``~/.pdbrc`` file. If you are programmatically using the - Pdb instance you can also change the ``default_predicates`` class - attribute. - """ - if not args.strip(): - print("current predicates:") - for (p, v) in self._predicates.items(): - print(" ", p, ":", v) - return - type_value = args.strip().split(" ") - if len(type_value) != 2: - print( - f"Usage: skip_predicates <type> <value>, with <type> one of {set(self._predicates.keys())}" - ) - return - - type_, value = type_value - if type_ not in self._predicates: - print(f"{type_!r} not in {set(self._predicates.keys())}") - return - if value.lower() not in ("true", "yes", "1", "no", "false", "0"): - print( - f"{value!r} is invalid - use one of ('true', 'yes', '1', 'no', 'false', '0')" - ) - return - - self._predicates[type_] = value.lower() in ("true", "yes", "1") - if not any(self._predicates.values()): - print( - "Warning, all predicates set to False, skip_hidden may not have any effects." - ) - - def do_skip_hidden(self, arg): - """ - Change whether or not we should skip frames with the - __tracebackhide__ attribute. - """ - if not arg.strip(): - print( - f"skip_hidden = {self.skip_hidden}, use 'yes','no', 'true', or 'false' to change." - ) - elif arg.strip().lower() in ("true", "yes"): - self.skip_hidden = True - elif arg.strip().lower() in ("false", "no"): - self.skip_hidden = False - if not any(self._predicates.values()): - print( - "Warning, all predicates set to False, skip_hidden may not have any effects." - ) - - def do_list(self, arg): - """Print lines of code from the current stack frame - """ - self.lastcmd = 'list' - last = None - if arg: - try: - x = eval(arg, {}, {}) - if type(x) == type(()): - first, last = x - first = int(first) - last = int(last) - if last < first: - # Assume it's a count - last = first + last - else: - first = max(1, int(x) - 5) - except: - print('*** Error in argument:', repr(arg), file=self.stdout) - return - elif self.lineno is None: - first = max(1, self.curframe.f_lineno - 5) - else: - first = self.lineno + 1 - if last is None: - last = first + 10 - self.print_list_lines(self.curframe.f_code.co_filename, first, last) - - # vds: >> - lineno = first - filename = self.curframe.f_code.co_filename - self.shell.hooks.synchronize_with_editor(filename, lineno, 0) - # vds: << - - do_l = do_list - - def getsourcelines(self, obj): - lines, lineno = inspect.findsource(obj) - if inspect.isframe(obj) and obj.f_globals is self._get_frame_locals(obj): - # must be a module frame: do not try to cut a block out of it - return lines, 1 - elif inspect.ismodule(obj): - return lines, 1 - return inspect.getblock(lines[lineno:]), lineno+1 - - def do_longlist(self, arg): - """Print lines of code from the current stack frame. - - Shows more lines than 'list' does. - """ - self.lastcmd = 'longlist' - try: - lines, lineno = self.getsourcelines(self.curframe) - except OSError as err: - self.error(err) - return - last = lineno + len(lines) - self.print_list_lines(self.curframe.f_code.co_filename, lineno, last) - do_ll = do_longlist - - def do_debug(self, arg): - """debug code - Enter a recursive debugger that steps through the code - argument (which is an arbitrary expression or statement to be - executed in the current environment). - """ - trace_function = sys.gettrace() - sys.settrace(None) - globals = self.curframe.f_globals - locals = self.curframe_locals - p = self.__class__(completekey=self.completekey, - stdin=self.stdin, stdout=self.stdout) - p.use_rawinput = self.use_rawinput - p.prompt = "(%s) " % self.prompt.strip() - self.message("ENTERING RECURSIVE DEBUGGER") - sys.call_tracing(p.run, (arg, globals, locals)) - self.message("LEAVING RECURSIVE DEBUGGER") - sys.settrace(trace_function) - self.lastcmd = p.lastcmd - - def do_pdef(self, arg): - """Print the call signature for any callable object. - - The debugger interface to %pdef""" - namespaces = [ - ("Locals", self.curframe_locals), - ("Globals", self.curframe.f_globals), - ] - self.shell.find_line_magic("pdef")(arg, namespaces=namespaces) - - def do_pdoc(self, arg): - """Print the docstring for an object. - - The debugger interface to %pdoc.""" - namespaces = [ - ("Locals", self.curframe_locals), - ("Globals", self.curframe.f_globals), - ] - self.shell.find_line_magic("pdoc")(arg, namespaces=namespaces) - - def do_pfile(self, arg): - """Print (or run through pager) the file where an object is defined. - - The debugger interface to %pfile. - """ - namespaces = [ - ("Locals", self.curframe_locals), - ("Globals", self.curframe.f_globals), - ] - self.shell.find_line_magic("pfile")(arg, namespaces=namespaces) - - def do_pinfo(self, arg): - """Provide detailed information about an object. - - The debugger interface to %pinfo, i.e., obj?.""" - namespaces = [ - ("Locals", self.curframe_locals), - ("Globals", self.curframe.f_globals), - ] - self.shell.find_line_magic("pinfo")(arg, namespaces=namespaces) - - def do_pinfo2(self, arg): - """Provide extra detailed information about an object. - - The debugger interface to %pinfo2, i.e., obj??.""" - namespaces = [ - ("Locals", self.curframe_locals), - ("Globals", self.curframe.f_globals), - ] - self.shell.find_line_magic("pinfo2")(arg, namespaces=namespaces) - - def do_psource(self, arg): - """Print (or run through pager) the source code for an object.""" - namespaces = [ - ("Locals", self.curframe_locals), - ("Globals", self.curframe.f_globals), - ] - self.shell.find_line_magic("psource")(arg, namespaces=namespaces) - - def do_where(self, arg): - """w(here) - Print a stack trace, with the most recent frame at the bottom. - An arrow indicates the "current frame", which determines the - context of most commands. 'bt' is an alias for this command. - - Take a number as argument as an (optional) number of context line to - print""" - if arg: - try: - context = int(arg) - except ValueError as err: - self.error(err) - return - self.print_stack_trace(context) - else: - self.print_stack_trace() - - do_w = do_where - - def break_anywhere(self, frame): - """ - _stop_in_decorator_internals is overly restrictive, as we may still want - to trace function calls, so we need to also update break_anywhere so - that is we don't `stop_here`, because of debugger skip, we may still - stop at any point inside the function - - """ - - sup = super().break_anywhere(frame) - if sup: - return sup - if self._predicates["debuggerskip"]: - if DEBUGGERSKIP in frame.f_code.co_varnames: - return True - if frame.f_back and self._get_frame_locals(frame.f_back).get(DEBUGGERSKIP): - return True - return False - - def _is_in_decorator_internal_and_should_skip(self, frame): - """ - Utility to tell us whether we are in a decorator internal and should stop. - - """ - - # if we are disabled don't skip - if not self._predicates["debuggerskip"]: - return False - - # if frame is tagged, skip by default. - if DEBUGGERSKIP in frame.f_code.co_varnames: - return True - - # if one of the parent frame value set to True skip as well. - - cframe = frame - while getattr(cframe, "f_back", None): - cframe = cframe.f_back - if self._get_frame_locals(cframe).get(DEBUGGERSKIP): - return True - - return False - - def stop_here(self, frame): - - if self._is_in_decorator_internal_and_should_skip(frame) is True: - return False - - hidden = False - if self.skip_hidden: - hidden = self._hidden_predicate(frame) - if hidden: - if self.report_skipped: - Colors = self.color_scheme_table.active_colors - ColorsNormal = Colors.Normal - print( - f"{Colors.excName} [... skipped 1 hidden frame]{ColorsNormal}\n" - ) - return super().stop_here(frame) - - def do_up(self, arg): - """u(p) [count] - Move the current frame count (default one) levels up in the - stack trace (to an older frame). - - Will skip hidden frames. - """ - # modified version of upstream that skips - # frames with __tracebackhide__ - if self.curindex == 0: - self.error("Oldest frame") - return - try: - count = int(arg or 1) - except ValueError: - self.error("Invalid frame count (%s)" % arg) - return - skipped = 0 - if count < 0: - _newframe = 0 - else: - counter = 0 - hidden_frames = self.hidden_frames(self.stack) - for i in range(self.curindex - 1, -1, -1): - if hidden_frames[i] and self.skip_hidden: - skipped += 1 - continue - counter += 1 - if counter >= count: - break - else: - # if no break occurred. - self.error( - "all frames above hidden, use `skip_hidden False` to get get into those." - ) - return - - Colors = self.color_scheme_table.active_colors - ColorsNormal = Colors.Normal - _newframe = i - self._select_frame(_newframe) - if skipped: - print( - f"{Colors.excName} [... skipped {skipped} hidden frame(s)]{ColorsNormal}\n" - ) - - def do_down(self, arg): - """d(own) [count] - Move the current frame count (default one) levels down in the - stack trace (to a newer frame). - - Will skip hidden frames. - """ - if self.curindex + 1 == len(self.stack): - self.error("Newest frame") - return - try: - count = int(arg or 1) - except ValueError: - self.error("Invalid frame count (%s)" % arg) - return - if count < 0: - _newframe = len(self.stack) - 1 - else: - counter = 0 - skipped = 0 - hidden_frames = self.hidden_frames(self.stack) - for i in range(self.curindex + 1, len(self.stack)): - if hidden_frames[i] and self.skip_hidden: - skipped += 1 - continue - counter += 1 - if counter >= count: - break - else: - self.error( - "all frames below hidden, use `skip_hidden False` to get get into those." - ) - return - - Colors = self.color_scheme_table.active_colors - ColorsNormal = Colors.Normal - if skipped: - print( - f"{Colors.excName} [... skipped {skipped} hidden frame(s)]{ColorsNormal}\n" - ) - _newframe = i - - self._select_frame(_newframe) - - do_d = do_down - do_u = do_up - - def do_context(self, context): - """context number_of_lines - Set the number of lines of source code to show when displaying - stacktrace information. - """ - try: - new_context = int(context) - if new_context <= 0: - raise ValueError() - self.context = new_context - except ValueError: - self.error("The 'context' command requires a positive integer argument.") - - -class InterruptiblePdb(Pdb): - """Version of debugger where KeyboardInterrupt exits the debugger altogether.""" - - def cmdloop(self, intro=None): - """Wrap cmdloop() such that KeyboardInterrupt stops the debugger.""" - try: - return OldPdb.cmdloop(self, intro=intro) - except KeyboardInterrupt: - self.stop_here = lambda frame: False - self.do_quit("") - sys.settrace(None) - self.quitting = False - raise - - def _cmdloop(self): - while True: - try: - # keyboard interrupts allow for an easy way to cancel - # the current command, so allow them during interactive input - self.allow_kbdint = True - self.cmdloop() - self.allow_kbdint = False - break - except KeyboardInterrupt: - self.message('--KeyboardInterrupt--') - raise - - -def set_trace(frame=None): - """ - Start debugging from `frame`. - - If frame is not specified, debugging starts from caller's frame. - """ - Pdb().set_trace(frame or sys._getframe().f_back) diff --git a/contrib/python/ipython/py3/IPython/core/display.py b/contrib/python/ipython/py3/IPython/core/display.py deleted file mode 100644 index 933295ad6c..0000000000 --- a/contrib/python/ipython/py3/IPython/core/display.py +++ /dev/null @@ -1,1277 +0,0 @@ -# -*- coding: utf-8 -*- -"""Top-level display functions for displaying object in different formats.""" - -# Copyright (c) IPython Development Team. -# Distributed under the terms of the Modified BSD License. - - -from binascii import b2a_base64, hexlify -import html -import json -import mimetypes -import os -import struct -import warnings -from copy import deepcopy -from os.path import splitext -from pathlib import Path, PurePath - -from IPython.utils.py3compat import cast_unicode -from IPython.testing.skipdoctest import skip_doctest -from . import display_functions - - -__all__ = ['display_pretty', 'display_html', 'display_markdown', - 'display_svg', 'display_png', 'display_jpeg', 'display_latex', 'display_json', - 'display_javascript', 'display_pdf', 'DisplayObject', 'TextDisplayObject', - 'Pretty', 'HTML', 'Markdown', 'Math', 'Latex', 'SVG', 'ProgressBar', 'JSON', - 'GeoJSON', 'Javascript', 'Image', 'set_matplotlib_formats', - 'set_matplotlib_close', - 'Video'] - -_deprecated_names = ["display", "clear_output", "publish_display_data", "update_display", "DisplayHandle"] - -__all__ = __all__ + _deprecated_names - - -# ----- warn to import from IPython.display ----- - -from warnings import warn - - -def __getattr__(name): - if name in _deprecated_names: - warn(f"Importing {name} from IPython.core.display is deprecated since IPython 7.14, please import from IPython display", DeprecationWarning, stacklevel=2) - return getattr(display_functions, name) - - if name in globals().keys(): - return globals()[name] - else: - raise AttributeError(f"module {__name__} has no attribute {name}") - - -#----------------------------------------------------------------------------- -# utility functions -#----------------------------------------------------------------------------- - -def _safe_exists(path): - """Check path, but don't let exceptions raise""" - try: - return os.path.exists(path) - except Exception: - return False - - -def _display_mimetype(mimetype, objs, raw=False, metadata=None): - """internal implementation of all display_foo methods - - Parameters - ---------- - mimetype : str - The mimetype to be published (e.g. 'image/png') - *objs : object - The Python objects to display, or if raw=True raw text data to - display. - raw : bool - Are the data objects raw data or Python objects that need to be - formatted before display? [default: False] - metadata : dict (optional) - Metadata to be associated with the specific mimetype output. - """ - if metadata: - metadata = {mimetype: metadata} - if raw: - # turn list of pngdata into list of { 'image/png': pngdata } - objs = [ {mimetype: obj} for obj in objs ] - display_functions.display(*objs, raw=raw, metadata=metadata, include=[mimetype]) - -#----------------------------------------------------------------------------- -# Main functions -#----------------------------------------------------------------------------- - - -def display_pretty(*objs, **kwargs): - """Display the pretty (default) representation of an object. - - Parameters - ---------- - *objs : object - The Python objects to display, or if raw=True raw text data to - display. - raw : bool - Are the data objects raw data or Python objects that need to be - formatted before display? [default: False] - metadata : dict (optional) - Metadata to be associated with the specific mimetype output. - """ - _display_mimetype('text/plain', objs, **kwargs) - - -def display_html(*objs, **kwargs): - """Display the HTML representation of an object. - - Note: If raw=False and the object does not have a HTML - representation, no HTML will be shown. - - Parameters - ---------- - *objs : object - The Python objects to display, or if raw=True raw HTML data to - display. - raw : bool - Are the data objects raw data or Python objects that need to be - formatted before display? [default: False] - metadata : dict (optional) - Metadata to be associated with the specific mimetype output. - """ - _display_mimetype('text/html', objs, **kwargs) - - -def display_markdown(*objs, **kwargs): - """Displays the Markdown representation of an object. - - Parameters - ---------- - *objs : object - The Python objects to display, or if raw=True raw markdown data to - display. - raw : bool - Are the data objects raw data or Python objects that need to be - formatted before display? [default: False] - metadata : dict (optional) - Metadata to be associated with the specific mimetype output. - """ - - _display_mimetype('text/markdown', objs, **kwargs) - - -def display_svg(*objs, **kwargs): - """Display the SVG representation of an object. - - Parameters - ---------- - *objs : object - The Python objects to display, or if raw=True raw svg data to - display. - raw : bool - Are the data objects raw data or Python objects that need to be - formatted before display? [default: False] - metadata : dict (optional) - Metadata to be associated with the specific mimetype output. - """ - _display_mimetype('image/svg+xml', objs, **kwargs) - - -def display_png(*objs, **kwargs): - """Display the PNG representation of an object. - - Parameters - ---------- - *objs : object - The Python objects to display, or if raw=True raw png data to - display. - raw : bool - Are the data objects raw data or Python objects that need to be - formatted before display? [default: False] - metadata : dict (optional) - Metadata to be associated with the specific mimetype output. - """ - _display_mimetype('image/png', objs, **kwargs) - - -def display_jpeg(*objs, **kwargs): - """Display the JPEG representation of an object. - - Parameters - ---------- - *objs : object - The Python objects to display, or if raw=True raw JPEG data to - display. - raw : bool - Are the data objects raw data or Python objects that need to be - formatted before display? [default: False] - metadata : dict (optional) - Metadata to be associated with the specific mimetype output. - """ - _display_mimetype('image/jpeg', objs, **kwargs) - - -def display_latex(*objs, **kwargs): - """Display the LaTeX representation of an object. - - Parameters - ---------- - *objs : object - The Python objects to display, or if raw=True raw latex data to - display. - raw : bool - Are the data objects raw data or Python objects that need to be - formatted before display? [default: False] - metadata : dict (optional) - Metadata to be associated with the specific mimetype output. - """ - _display_mimetype('text/latex', objs, **kwargs) - - -def display_json(*objs, **kwargs): - """Display the JSON representation of an object. - - Note that not many frontends support displaying JSON. - - Parameters - ---------- - *objs : object - The Python objects to display, or if raw=True raw json data to - display. - raw : bool - Are the data objects raw data or Python objects that need to be - formatted before display? [default: False] - metadata : dict (optional) - Metadata to be associated with the specific mimetype output. - """ - _display_mimetype('application/json', objs, **kwargs) - - -def display_javascript(*objs, **kwargs): - """Display the Javascript representation of an object. - - Parameters - ---------- - *objs : object - The Python objects to display, or if raw=True raw javascript data to - display. - raw : bool - Are the data objects raw data or Python objects that need to be - formatted before display? [default: False] - metadata : dict (optional) - Metadata to be associated with the specific mimetype output. - """ - _display_mimetype('application/javascript', objs, **kwargs) - - -def display_pdf(*objs, **kwargs): - """Display the PDF representation of an object. - - Parameters - ---------- - *objs : object - The Python objects to display, or if raw=True raw javascript data to - display. - raw : bool - Are the data objects raw data or Python objects that need to be - formatted before display? [default: False] - metadata : dict (optional) - Metadata to be associated with the specific mimetype output. - """ - _display_mimetype('application/pdf', objs, **kwargs) - - -#----------------------------------------------------------------------------- -# Smart classes -#----------------------------------------------------------------------------- - - -class DisplayObject(object): - """An object that wraps data to be displayed.""" - - _read_flags = 'r' - _show_mem_addr = False - metadata = None - - def __init__(self, data=None, url=None, filename=None, metadata=None): - """Create a display object given raw data. - - When this object is returned by an expression or passed to the - display function, it will result in the data being displayed - in the frontend. The MIME type of the data should match the - subclasses used, so the Png subclass should be used for 'image/png' - data. If the data is a URL, the data will first be downloaded - and then displayed. If - - Parameters - ---------- - data : unicode, str or bytes - The raw data or a URL or file to load the data from - url : unicode - A URL to download the data from. - filename : unicode - Path to a local file to load the data from. - metadata : dict - Dict of metadata associated to be the object when displayed - """ - if isinstance(data, (Path, PurePath)): - data = str(data) - - if data is not None and isinstance(data, str): - if data.startswith('http') and url is None: - url = data - filename = None - data = None - elif _safe_exists(data) and filename is None: - url = None - filename = data - data = None - - self.url = url - self.filename = filename - # because of @data.setter methods in - # subclasses ensure url and filename are set - # before assigning to self.data - self.data = data - - if metadata is not None: - self.metadata = metadata - elif self.metadata is None: - self.metadata = {} - - self.reload() - self._check_data() - - def __repr__(self): - if not self._show_mem_addr: - cls = self.__class__ - r = "<%s.%s object>" % (cls.__module__, cls.__name__) - else: - r = super(DisplayObject, self).__repr__() - return r - - def _check_data(self): - """Override in subclasses if there's something to check.""" - pass - - def _data_and_metadata(self): - """shortcut for returning metadata with shape information, if defined""" - if self.metadata: - return self.data, deepcopy(self.metadata) - else: - return self.data - - def reload(self): - """Reload the raw data from file or URL.""" - if self.filename is not None: - encoding = None if "b" in self._read_flags else "utf-8" - with open(self.filename, self._read_flags, encoding=encoding) as f: - self.data = f.read() - elif self.url is not None: - # Deferred import - from urllib.request import urlopen - response = urlopen(self.url) - data = response.read() - # extract encoding from header, if there is one: - encoding = None - if 'content-type' in response.headers: - for sub in response.headers['content-type'].split(';'): - sub = sub.strip() - if sub.startswith('charset'): - encoding = sub.split('=')[-1].strip() - break - if 'content-encoding' in response.headers: - # TODO: do deflate? - if 'gzip' in response.headers['content-encoding']: - import gzip - from io import BytesIO - - # assume utf-8 if encoding is not specified - with gzip.open( - BytesIO(data), "rt", encoding=encoding or "utf-8" - ) as fp: - encoding = None - data = fp.read() - - # decode data, if an encoding was specified - # We only touch self.data once since - # subclasses such as SVG have @data.setter methods - # that transform self.data into ... well svg. - if encoding: - self.data = data.decode(encoding, 'replace') - else: - self.data = data - - -class TextDisplayObject(DisplayObject): - """Validate that display data is text""" - def _check_data(self): - if self.data is not None and not isinstance(self.data, str): - raise TypeError("%s expects text, not %r" % (self.__class__.__name__, self.data)) - -class Pretty(TextDisplayObject): - - def _repr_pretty_(self, pp, cycle): - return pp.text(self.data) - - -class HTML(TextDisplayObject): - - def __init__(self, data=None, url=None, filename=None, metadata=None): - def warn(): - if not data: - return False - - # - # Avoid calling lower() on the entire data, because it could be a - # long string and we're only interested in its beginning and end. - # - prefix = data[:10].lower() - suffix = data[-10:].lower() - return prefix.startswith("<iframe ") and suffix.endswith("</iframe>") - - if warn(): - warnings.warn("Consider using IPython.display.IFrame instead") - super(HTML, self).__init__(data=data, url=url, filename=filename, metadata=metadata) - - def _repr_html_(self): - return self._data_and_metadata() - - def __html__(self): - """ - This method exists to inform other HTML-using modules (e.g. Markupsafe, - htmltag, etc) that this object is HTML and does not need things like - special characters (<>&) escaped. - """ - return self._repr_html_() - - -class Markdown(TextDisplayObject): - - def _repr_markdown_(self): - return self._data_and_metadata() - - -class Math(TextDisplayObject): - - def _repr_latex_(self): - s = r"$\displaystyle %s$" % self.data.strip('$') - if self.metadata: - return s, deepcopy(self.metadata) - else: - return s - - -class Latex(TextDisplayObject): - - def _repr_latex_(self): - return self._data_and_metadata() - - -class SVG(DisplayObject): - """Embed an SVG into the display. - - Note if you just want to view a svg image via a URL use `:class:Image` with - a url=URL keyword argument. - """ - - _read_flags = 'rb' - # wrap data in a property, which extracts the <svg> tag, discarding - # document headers - _data = None - - @property - def data(self): - return self._data - - @data.setter - def data(self, svg): - if svg is None: - self._data = None - return - # parse into dom object - from xml.dom import minidom - x = minidom.parseString(svg) - # get svg tag (should be 1) - found_svg = x.getElementsByTagName('svg') - if found_svg: - svg = found_svg[0].toxml() - else: - # fallback on the input, trust the user - # but this is probably an error. - pass - svg = cast_unicode(svg) - self._data = svg - - def _repr_svg_(self): - return self._data_and_metadata() - -class ProgressBar(DisplayObject): - """Progressbar supports displaying a progressbar like element - """ - def __init__(self, total): - """Creates a new progressbar - - Parameters - ---------- - total : int - maximum size of the progressbar - """ - self.total = total - self._progress = 0 - self.html_width = '60ex' - self.text_width = 60 - self._display_id = hexlify(os.urandom(8)).decode('ascii') - - def __repr__(self): - fraction = self.progress / self.total - filled = '=' * int(fraction * self.text_width) - rest = ' ' * (self.text_width - len(filled)) - return '[{}{}] {}/{}'.format( - filled, rest, - self.progress, self.total, - ) - - def _repr_html_(self): - return "<progress style='width:{}' max='{}' value='{}'></progress>".format( - self.html_width, self.total, self.progress) - - def display(self): - display_functions.display(self, display_id=self._display_id) - - def update(self): - display_functions.display(self, display_id=self._display_id, update=True) - - @property - def progress(self): - return self._progress - - @progress.setter - def progress(self, value): - self._progress = value - self.update() - - def __iter__(self): - self.display() - self._progress = -1 # First iteration is 0 - return self - - def __next__(self): - """Returns current value and increments display by one.""" - self.progress += 1 - if self.progress < self.total: - return self.progress - else: - raise StopIteration() - -class JSON(DisplayObject): - """JSON expects a JSON-able dict or list - - not an already-serialized JSON string. - - Scalar types (None, number, string) are not allowed, only dict or list containers. - """ - # wrap data in a property, which warns about passing already-serialized JSON - _data = None - def __init__(self, data=None, url=None, filename=None, expanded=False, metadata=None, root='root', **kwargs): - """Create a JSON display object given raw data. - - Parameters - ---------- - data : dict or list - JSON data to display. Not an already-serialized JSON string. - Scalar types (None, number, string) are not allowed, only dict - or list containers. - url : unicode - A URL to download the data from. - filename : unicode - Path to a local file to load the data from. - expanded : boolean - Metadata to control whether a JSON display component is expanded. - metadata : dict - Specify extra metadata to attach to the json display object. - root : str - The name of the root element of the JSON tree - """ - self.metadata = { - 'expanded': expanded, - 'root': root, - } - if metadata: - self.metadata.update(metadata) - if kwargs: - self.metadata.update(kwargs) - super(JSON, self).__init__(data=data, url=url, filename=filename) - - def _check_data(self): - if self.data is not None and not isinstance(self.data, (dict, list)): - raise TypeError("%s expects JSONable dict or list, not %r" % (self.__class__.__name__, self.data)) - - @property - def data(self): - return self._data - - @data.setter - def data(self, data): - if isinstance(data, (Path, PurePath)): - data = str(data) - - if isinstance(data, str): - if self.filename is None and self.url is None: - warnings.warn("JSON expects JSONable dict or list, not JSON strings") - data = json.loads(data) - self._data = data - - def _data_and_metadata(self): - return self.data, self.metadata - - def _repr_json_(self): - return self._data_and_metadata() - -_css_t = """var link = document.createElement("link"); - link.ref = "stylesheet"; - link.type = "text/css"; - link.href = "%s"; - document.head.appendChild(link); -""" - -_lib_t1 = """new Promise(function(resolve, reject) { - var script = document.createElement("script"); - script.onload = resolve; - script.onerror = reject; - script.src = "%s"; - document.head.appendChild(script); -}).then(() => { -""" - -_lib_t2 = """ -});""" - -class GeoJSON(JSON): - """GeoJSON expects JSON-able dict - - not an already-serialized JSON string. - - Scalar types (None, number, string) are not allowed, only dict containers. - """ - - def __init__(self, *args, **kwargs): - """Create a GeoJSON display object given raw data. - - Parameters - ---------- - data : dict or list - VegaLite data. Not an already-serialized JSON string. - Scalar types (None, number, string) are not allowed, only dict - or list containers. - url_template : string - Leaflet TileLayer URL template: http://leafletjs.com/reference.html#url-template - layer_options : dict - Leaflet TileLayer options: http://leafletjs.com/reference.html#tilelayer-options - url : unicode - A URL to download the data from. - filename : unicode - Path to a local file to load the data from. - metadata : dict - Specify extra metadata to attach to the json display object. - - Examples - -------- - The following will display an interactive map of Mars with a point of - interest on frontend that do support GeoJSON display. - - >>> from IPython.display import GeoJSON - - >>> GeoJSON(data={ - ... "type": "Feature", - ... "geometry": { - ... "type": "Point", - ... "coordinates": [-81.327, 296.038] - ... } - ... }, - ... url_template="http://s3-eu-west-1.amazonaws.com/whereonmars.cartodb.net/{basemap_id}/{z}/{x}/{y}.png", - ... layer_options={ - ... "basemap_id": "celestia_mars-shaded-16k_global", - ... "attribution" : "Celestia/praesepe", - ... "minZoom" : 0, - ... "maxZoom" : 18, - ... }) - <IPython.core.display.GeoJSON object> - - In the terminal IPython, you will only see the text representation of - the GeoJSON object. - - """ - - super(GeoJSON, self).__init__(*args, **kwargs) - - - def _ipython_display_(self): - bundle = { - 'application/geo+json': self.data, - 'text/plain': '<IPython.display.GeoJSON object>' - } - metadata = { - 'application/geo+json': self.metadata - } - display_functions.display(bundle, metadata=metadata, raw=True) - -class Javascript(TextDisplayObject): - - def __init__(self, data=None, url=None, filename=None, lib=None, css=None): - """Create a Javascript display object given raw data. - - When this object is returned by an expression or passed to the - display function, it will result in the data being displayed - in the frontend. If the data is a URL, the data will first be - downloaded and then displayed. - - In the Notebook, the containing element will be available as `element`, - and jQuery will be available. Content appended to `element` will be - visible in the output area. - - Parameters - ---------- - data : unicode, str or bytes - The Javascript source code or a URL to download it from. - url : unicode - A URL to download the data from. - filename : unicode - Path to a local file to load the data from. - lib : list or str - A sequence of Javascript library URLs to load asynchronously before - running the source code. The full URLs of the libraries should - be given. A single Javascript library URL can also be given as a - string. - css : list or str - A sequence of css files to load before running the source code. - The full URLs of the css files should be given. A single css URL - can also be given as a string. - """ - if isinstance(lib, str): - lib = [lib] - elif lib is None: - lib = [] - if isinstance(css, str): - css = [css] - elif css is None: - css = [] - if not isinstance(lib, (list,tuple)): - raise TypeError('expected sequence, got: %r' % lib) - if not isinstance(css, (list,tuple)): - raise TypeError('expected sequence, got: %r' % css) - self.lib = lib - self.css = css - super(Javascript, self).__init__(data=data, url=url, filename=filename) - - def _repr_javascript_(self): - r = '' - for c in self.css: - r += _css_t % c - for l in self.lib: - r += _lib_t1 % l - r += self.data - r += _lib_t2*len(self.lib) - return r - -# constants for identifying png/jpeg data -_PNG = b'\x89PNG\r\n\x1a\n' -_JPEG = b'\xff\xd8' - -def _pngxy(data): - """read the (width, height) from a PNG header""" - ihdr = data.index(b'IHDR') - # next 8 bytes are width/height - return struct.unpack('>ii', data[ihdr+4:ihdr+12]) - -def _jpegxy(data): - """read the (width, height) from a JPEG header""" - # adapted from http://www.64lines.com/jpeg-width-height - - idx = 4 - while True: - block_size = struct.unpack('>H', data[idx:idx+2])[0] - idx = idx + block_size - if data[idx:idx+2] == b'\xFF\xC0': - # found Start of Frame - iSOF = idx - break - else: - # read another block - idx += 2 - - h, w = struct.unpack('>HH', data[iSOF+5:iSOF+9]) - return w, h - -def _gifxy(data): - """read the (width, height) from a GIF header""" - return struct.unpack('<HH', data[6:10]) - - -class Image(DisplayObject): - - _read_flags = 'rb' - _FMT_JPEG = u'jpeg' - _FMT_PNG = u'png' - _FMT_GIF = u'gif' - _ACCEPTABLE_EMBEDDINGS = [_FMT_JPEG, _FMT_PNG, _FMT_GIF] - _MIMETYPES = { - _FMT_PNG: 'image/png', - _FMT_JPEG: 'image/jpeg', - _FMT_GIF: 'image/gif', - } - - def __init__( - self, - data=None, - url=None, - filename=None, - format=None, - embed=None, - width=None, - height=None, - retina=False, - unconfined=False, - metadata=None, - alt=None, - ): - """Create a PNG/JPEG/GIF image object given raw data. - - When this object is returned by an input cell or passed to the - display function, it will result in the image being displayed - in the frontend. - - Parameters - ---------- - data : unicode, str or bytes - The raw image data or a URL or filename to load the data from. - This always results in embedded image data. - - url : unicode - A URL to download the data from. If you specify `url=`, - the image data will not be embedded unless you also specify `embed=True`. - - filename : unicode - Path to a local file to load the data from. - Images from a file are always embedded. - - format : unicode - The format of the image data (png/jpeg/jpg/gif). If a filename or URL is given - for format will be inferred from the filename extension. - - embed : bool - Should the image data be embedded using a data URI (True) or be - loaded using an <img> tag. Set this to True if you want the image - to be viewable later with no internet connection in the notebook. - - Default is `True`, unless the keyword argument `url` is set, then - default value is `False`. - - 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 - - height : int - 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. - This only works for embedded images because it reads the width/height - from image data. - For non-embedded images, you can just set the desired display width - and height directly. - - unconfined : bool - Set unconfined=True to disable max-width confinement of the image. - - metadata : dict - Specify extra metadata to attach to the image. - - alt : unicode - Alternative text for the image, for use by screen readers. - - Examples - -------- - embedded image data, works in qtconsole and notebook - when passed positionally, the first arg can be any of raw image data, - a URL, or a filename from which to load image data. - The result is always embedding image data for inline images. - - >>> Image('https://www.google.fr/images/srpr/logo3w.png') # doctest: +SKIP - <IPython.core.display.Image object> - - >>> Image('/path/to/image.jpg') - <IPython.core.display.Image object> - - >>> Image(b'RAW_PNG_DATA...') - <IPython.core.display.Image object> - - Specifying Image(url=...) does not embed the image data, - it only generates ``<img>`` tag with a link to the source. - This will not work in the qtconsole or offline. - - >>> Image(url='https://www.google.fr/images/srpr/logo3w.png') - <IPython.core.display.Image object> - - """ - if isinstance(data, (Path, PurePath)): - data = str(data) - - if filename is not None: - ext = self._find_ext(filename) - elif url is not None: - ext = self._find_ext(url) - elif data is None: - raise ValueError("No image data found. Expecting filename, url, or data.") - elif isinstance(data, str) and ( - data.startswith('http') or _safe_exists(data) - ): - ext = self._find_ext(data) - else: - ext = None - - if format is None: - if ext is not None: - if ext == u'jpg' or ext == u'jpeg': - format = self._FMT_JPEG - elif ext == u'png': - format = self._FMT_PNG - elif ext == u'gif': - format = self._FMT_GIF - else: - format = ext.lower() - elif isinstance(data, bytes): - # infer image type from image data header, - # only if format has not been specified. - if data[:2] == _JPEG: - format = self._FMT_JPEG - - # failed to detect format, default png - if format is None: - format = self._FMT_PNG - - if format.lower() == 'jpg': - # jpg->jpeg - format = self._FMT_JPEG - - self.format = format.lower() - self.embed = embed if embed is not None else (url is None) - - if self.embed and self.format not in self._ACCEPTABLE_EMBEDDINGS: - raise ValueError("Cannot embed the '%s' image format" % (self.format)) - if self.embed: - self._mimetype = self._MIMETYPES.get(self.format) - - self.width = width - self.height = height - self.retina = retina - self.unconfined = unconfined - self.alt = alt - super(Image, self).__init__(data=data, url=url, filename=filename, - metadata=metadata) - - if self.width is None and self.metadata.get('width', {}): - self.width = metadata['width'] - - if self.height is None and self.metadata.get('height', {}): - self.height = metadata['height'] - - if self.alt is None and self.metadata.get("alt", {}): - self.alt = metadata["alt"] - - if retina: - self._retina_shape() - - - def _retina_shape(self): - """load pixel-doubled width and height from image data""" - if not self.embed: - return - if self.format == self._FMT_PNG: - w, h = _pngxy(self.data) - elif self.format == self._FMT_JPEG: - w, h = _jpegxy(self.data) - elif self.format == self._FMT_GIF: - w, h = _gifxy(self.data) - else: - # retina only supports png - return - self.width = w // 2 - self.height = h // 2 - - def reload(self): - """Reload the raw data from file or URL.""" - if self.embed: - super(Image,self).reload() - if self.retina: - self._retina_shape() - - def _repr_html_(self): - if not self.embed: - width = height = klass = alt = "" - if self.width: - width = ' width="%d"' % self.width - if self.height: - height = ' height="%d"' % self.height - if self.unconfined: - klass = ' class="unconfined"' - if self.alt: - alt = ' alt="%s"' % html.escape(self.alt) - return '<img src="{url}"{width}{height}{klass}{alt}/>'.format( - url=self.url, - width=width, - height=height, - klass=klass, - alt=alt, - ) - - def _repr_mimebundle_(self, include=None, exclude=None): - """Return the image as a mimebundle - - Any new mimetype support should be implemented here. - """ - if self.embed: - mimetype = self._mimetype - data, metadata = self._data_and_metadata(always_both=True) - if metadata: - metadata = {mimetype: metadata} - return {mimetype: data}, metadata - else: - return {'text/html': self._repr_html_()} - - def _data_and_metadata(self, always_both=False): - """shortcut for returning metadata with shape information, if defined""" - try: - b64_data = b2a_base64(self.data).decode('ascii') - except TypeError as e: - raise FileNotFoundError( - "No such file or directory: '%s'" % (self.data)) from e - md = {} - if self.metadata: - md.update(self.metadata) - if self.width: - md['width'] = self.width - if self.height: - md['height'] = self.height - if self.unconfined: - md['unconfined'] = self.unconfined - if self.alt: - md["alt"] = self.alt - if md or always_both: - return b64_data, md - else: - return b64_data - - def _repr_png_(self): - if self.embed and self.format == self._FMT_PNG: - return self._data_and_metadata() - - def _repr_jpeg_(self): - if self.embed and self.format == self._FMT_JPEG: - return self._data_and_metadata() - - def _find_ext(self, s): - base, ext = splitext(s) - - if not ext: - return base - - # `splitext` includes leading period, so we skip it - return ext[1:].lower() - - -class Video(DisplayObject): - - def __init__(self, data=None, url=None, filename=None, embed=False, - mimetype=None, width=None, height=None, html_attributes="controls"): - """Create a video object given raw data or an URL. - - When this object is returned by an input cell or passed to the - display function, it will result in the video being displayed - in the frontend. - - 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``. - - url : unicode - 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``. - - 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:: - - Video('./video.mp4') - - mimetype : unicode - Specify the mimetype for embedded videos. - Default will be guessed from file extension, if available. - - width : int - Width in pixels to which to constrain the video in HTML. - If not supplied, defaults to the width of the video. - - height : int - Height in pixels to which to constrain the video in html. - If not supplied, defaults to the height of the video. - - html_attributes : str - Attributes for the HTML ``<video>`` block. - Default: ``"controls"`` to get video controls. - Other examples: ``"controls muted"`` for muted video with controls, - ``"loop autoplay"`` for looping autoplaying video without controls. - - 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('path/to/video.mp4', embed=True, html_attributes="controls muted autoplay") - Video(b'raw-videodata', embed=True) - """ - if isinstance(data, (Path, PurePath)): - data = str(data) - - if url is None and isinstance(data, str) and data.startswith(('http:', 'https:')): - url = data - data = None - elif data is not None and 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) - - self.mimetype = mimetype - self.embed = embed - self.width = width - self.height = height - self.html_attributes = html_attributes - super(Video, self).__init__(data=data, url=url, filename=filename) - - def _repr_html_(self): - width = height = '' - if self.width: - width = ' width="%d"' % self.width - if self.height: - height = ' height="%d"' % self.height - - # External URLs and potentially local files are not embedded into the - # notebook output. - if not self.embed: - url = self.url if self.url is not None else self.filename - output = """<video src="{0}" {1} {2} {3}> - Your browser does not support the <code>video</code> element. - </video>""".format(url, self.html_attributes, width, height) - return output - - # 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() - else: - video = self.data - if isinstance(video, str): - # unicode input is already b64-encoded - b64_video = video - else: - b64_video = b2a_base64(video).decode('ascii').rstrip() - - output = """<video {0} {1} {2}> - <source src="data:{3};base64,{4}" type="{3}"> - Your browser does not support the video tag. - </video>""".format(self.html_attributes, width, height, mimetype, b64_video) - return output - - def reload(self): - # TODO - pass - - -@skip_doctest -def set_matplotlib_formats(*formats, **kwargs): - """ - .. deprecated:: 7.23 - - use `matplotlib_inline.backend_inline.set_matplotlib_formats()` - - Select figure formats for the inline backend. Optionally pass quality for JPEG. - - For example, this enables PNG and JPEG output with a JPEG quality of 90%:: - - In [1]: set_matplotlib_formats('png', 'jpeg', quality=90) - - To set this in your config files use the following:: - - c.InlineBackend.figure_formats = {'png', 'jpeg'} - c.InlineBackend.print_figure_kwargs.update({'quality' : 90}) - - Parameters - ---------- - *formats : strs - One or more figure formats to enable: 'png', 'retina', 'jpeg', 'svg', 'pdf'. - **kwargs - Keyword args will be relayed to ``figure.canvas.print_figure``. - """ - warnings.warn( - "`set_matplotlib_formats` is deprecated since IPython 7.23, directly " - "use `matplotlib_inline.backend_inline.set_matplotlib_formats()`", - DeprecationWarning, - stacklevel=2, - ) - - from matplotlib_inline.backend_inline import ( - set_matplotlib_formats as set_matplotlib_formats_orig, - ) - - set_matplotlib_formats_orig(*formats, **kwargs) - -@skip_doctest -def set_matplotlib_close(close=True): - """ - .. deprecated:: 7.23 - - use `matplotlib_inline.backend_inline.set_matplotlib_close()` - - Set whether the inline backend closes all figures automatically or not. - - By default, the inline backend used in the IPython Notebook will close all - matplotlib figures automatically after each cell is run. This means that - plots in different cells won't interfere. Sometimes, you may want to make - a plot in one cell and then refine it in later cells. This can be accomplished - by:: - - In [1]: set_matplotlib_close(False) - - To set this in your config files use the following:: - - c.InlineBackend.close_figures = False - - Parameters - ---------- - close : bool - Should all matplotlib figures be automatically closed after each cell is - run? - """ - warnings.warn( - "`set_matplotlib_close` is deprecated since IPython 7.23, directly " - "use `matplotlib_inline.backend_inline.set_matplotlib_close()`", - DeprecationWarning, - stacklevel=2, - ) - - from matplotlib_inline.backend_inline import ( - set_matplotlib_close as set_matplotlib_close_orig, - ) - - set_matplotlib_close_orig(close) diff --git a/contrib/python/ipython/py3/IPython/core/display_functions.py b/contrib/python/ipython/py3/IPython/core/display_functions.py deleted file mode 100644 index 567cf3fa60..0000000000 --- a/contrib/python/ipython/py3/IPython/core/display_functions.py +++ /dev/null @@ -1,391 +0,0 @@ -# -*- coding: utf-8 -*- -"""Top-level display functions for displaying object in different formats.""" - -# Copyright (c) IPython Development Team. -# Distributed under the terms of the Modified BSD License. - - -from binascii import b2a_hex -import os -import sys -import warnings - -__all__ = ['display', 'clear_output', 'publish_display_data', 'update_display', 'DisplayHandle'] - -#----------------------------------------------------------------------------- -# utility functions -#----------------------------------------------------------------------------- - - -def _merge(d1, d2): - """Like update, but merges sub-dicts instead of clobbering at the top level. - - Updates d1 in-place - """ - - if not isinstance(d2, dict) or not isinstance(d1, dict): - return d2 - for key, value in d2.items(): - d1[key] = _merge(d1.get(key), value) - return d1 - - -#----------------------------------------------------------------------------- -# Main functions -#----------------------------------------------------------------------------- - -class _Sentinel: - def __repr__(self): - return "<deprecated>" - - -_sentinel = _Sentinel() - -# use * to indicate transient is keyword-only -def publish_display_data( - data, metadata=None, source=_sentinel, *, transient=None, **kwargs -): - """Publish data and metadata to all frontends. - - See the ``display_data`` message in the messaging documentation for - more details about this message type. - - Keys of data and metadata can be any mime-type. - - Parameters - ---------- - data : dict - A dictionary having keys that are valid MIME types (like - 'text/plain' or 'image/svg+xml') and values that are the data for - that MIME type. The data itself must be a JSON'able data - structure. Minimally all data should have the 'text/plain' data, - which can be displayed by all frontends. If more than the plain - text is given, it is up to the frontend to decide which - representation to use. - metadata : dict - A dictionary for metadata related to the data. This can contain - arbitrary key, value pairs that frontends can use to interpret - the data. mime-type keys matching those in data can be used - to specify metadata about particular representations. - source : str, deprecated - Unused. - transient : dict, keyword-only - A dictionary of transient data, such as display_id. - """ - from IPython.core.interactiveshell import InteractiveShell - - if source is not _sentinel: - warnings.warn( - "The `source` parameter emit a deprecation warning since" - " IPython 8.0, it had no effects for a long time and will " - " be removed in future versions.", - DeprecationWarning, - stacklevel=2, - ) - display_pub = InteractiveShell.instance().display_pub - - # only pass transient if supplied, - # to avoid errors with older ipykernel. - # TODO: We could check for ipykernel version and provide a detailed upgrade message. - if transient: - kwargs['transient'] = transient - - display_pub.publish( - data=data, - metadata=metadata, - **kwargs - ) - - -def _new_id(): - """Generate a new random text id with urandom""" - return b2a_hex(os.urandom(16)).decode('ascii') - - -def display( - *objs, - include=None, - exclude=None, - metadata=None, - transient=None, - display_id=None, - raw=False, - clear=False, - **kwargs -): - """Display a Python object in all frontends. - - By default all representations will be computed and sent to the frontends. - Frontends can decide which representation is used and how. - - In terminal IPython this will be similar to using :func:`print`, for use in richer - frontends see Jupyter notebook examples with rich display logic. - - Parameters - ---------- - *objs : object - The Python objects to display. - raw : bool, optional - Are the objects to be displayed already mimetype-keyed dicts of raw display data, - or Python objects that need to be formatted before display? [default: False] - include : list, tuple or set, optional - A list of format type strings (MIME types) to include in the - format data dict. If this is set *only* the format types included - in this list will be computed. - exclude : list, tuple or set, optional - A list of format type strings (MIME types) to exclude in the format - data dict. If this is set all format types will be computed, - except for those included in this argument. - metadata : dict, optional - A dictionary of metadata to associate with the output. - mime-type keys in this dictionary will be associated with the individual - representation formats, if they exist. - transient : dict, optional - A dictionary of transient data to associate with the output. - Data in this dict should not be persisted to files (e.g. notebooks). - display_id : str, bool optional - Set an id for the display. - This id can be used for updating this display area later via update_display. - If given as `True`, generate a new `display_id` - clear : bool, optional - Should the output area be cleared before displaying anything? If True, - this will wait for additional output before clearing. [default: False] - **kwargs : additional keyword-args, optional - Additional keyword-arguments are passed through to the display publisher. - - Returns - ------- - handle: DisplayHandle - Returns a handle on updatable displays for use with :func:`update_display`, - if `display_id` is given. Returns :any:`None` if no `display_id` is given - (default). - - Examples - -------- - >>> class Json(object): - ... def __init__(self, json): - ... self.json = json - ... def _repr_pretty_(self, pp, cycle): - ... import json - ... pp.text(json.dumps(self.json, indent=2)) - ... def __repr__(self): - ... return str(self.json) - ... - - >>> d = Json({1:2, 3: {4:5}}) - - >>> print(d) - {1: 2, 3: {4: 5}} - - >>> display(d) - { - "1": 2, - "3": { - "4": 5 - } - } - - >>> def int_formatter(integer, pp, cycle): - ... pp.text('I'*integer) - - >>> plain = get_ipython().display_formatter.formatters['text/plain'] - >>> plain.for_type(int, int_formatter) - <function _repr_pprint at 0x...> - >>> display(7-5) - II - - >>> del plain.type_printers[int] - >>> display(7-5) - 2 - - See Also - -------- - :func:`update_display` - - Notes - ----- - In Python, objects can declare their textual representation using the - `__repr__` method. IPython expands on this idea and allows objects to declare - other, rich representations including: - - - HTML - - JSON - - PNG - - JPEG - - SVG - - LaTeX - - A single object can declare some or all of these representations; all are - handled by IPython's display system. - - The main idea of the first approach is that you have to implement special - display methods when you define your class, one for each representation you - want to use. Here is a list of the names of the special methods and the - values they must return: - - - `_repr_html_`: return raw HTML as a string, or a tuple (see below). - - `_repr_json_`: return a JSONable dict, or a tuple (see below). - - `_repr_jpeg_`: return raw JPEG data, or a tuple (see below). - - `_repr_png_`: return raw PNG data, or a tuple (see below). - - `_repr_svg_`: return raw SVG data as a string, or a tuple (see below). - - `_repr_latex_`: return LaTeX commands in a string surrounded by "$", - or a tuple (see below). - - `_repr_mimebundle_`: return a full mimebundle containing the mapping - from all mimetypes to data. - Use this for any mime-type not listed above. - - The above functions may also return the object's metadata alonside the - data. If the metadata is available, the functions will return a tuple - containing the data and metadata, in that order. If there is no metadata - available, then the functions will return the data only. - - When you are directly writing your own classes, you can adapt them for - display in IPython by following the above approach. But in practice, you - often need to work with existing classes that you can't easily modify. - - You can refer to the documentation on integrating with the display system in - order to register custom formatters for already existing types - (:ref:`integrating_rich_display`). - - .. versionadded:: 5.4 display available without import - .. versionadded:: 6.1 display available without import - - Since IPython 5.4 and 6.1 :func:`display` is automatically made available to - the user without import. If you are using display in a document that might - be used in a pure python context or with older version of IPython, use the - following import at the top of your file:: - - from IPython.display import display - - """ - from IPython.core.interactiveshell import InteractiveShell - - if not InteractiveShell.initialized(): - # Directly print objects. - print(*objs) - return - - if transient is None: - transient = {} - if metadata is None: - metadata={} - if display_id: - if display_id is True: - display_id = _new_id() - transient['display_id'] = display_id - if kwargs.get('update') and 'display_id' not in transient: - raise TypeError('display_id required for update_display') - if transient: - kwargs['transient'] = transient - - if not objs and display_id: - # if given no objects, but still a request for a display_id, - # we assume the user wants to insert an empty output that - # can be updated later - objs = [{}] - raw = True - - if not raw: - format = InteractiveShell.instance().display_formatter.format - - if clear: - clear_output(wait=True) - - for obj in objs: - if raw: - publish_display_data(data=obj, metadata=metadata, **kwargs) - else: - format_dict, md_dict = format(obj, include=include, exclude=exclude) - if not format_dict: - # nothing to display (e.g. _ipython_display_ took over) - continue - if metadata: - # kwarg-specified metadata gets precedence - _merge(md_dict, metadata) - publish_display_data(data=format_dict, metadata=md_dict, **kwargs) - if display_id: - return DisplayHandle(display_id) - - -# use * for keyword-only display_id arg -def update_display(obj, *, display_id, **kwargs): - """Update an existing display by id - - Parameters - ---------- - obj - The object with which to update the display - display_id : keyword-only - The id of the display to update - - See Also - -------- - :func:`display` - """ - kwargs['update'] = True - display(obj, display_id=display_id, **kwargs) - - -class DisplayHandle(object): - """A handle on an updatable display - - Call `.update(obj)` to display a new object. - - Call `.display(obj`) to add a new instance of this display, - and update existing instances. - - See Also - -------- - - :func:`display`, :func:`update_display` - - """ - - def __init__(self, display_id=None): - if display_id is None: - display_id = _new_id() - self.display_id = display_id - - def __repr__(self): - return "<%s display_id=%s>" % (self.__class__.__name__, self.display_id) - - def display(self, obj, **kwargs): - """Make a new display with my id, updating existing instances. - - Parameters - ---------- - obj - object to display - **kwargs - additional keyword arguments passed to display - """ - display(obj, display_id=self.display_id, **kwargs) - - def update(self, obj, **kwargs): - """Update existing displays with my id - - Parameters - ---------- - obj - object to display - **kwargs - additional keyword arguments passed to update_display - """ - update_display(obj, display_id=self.display_id, **kwargs) - - -def clear_output(wait=False): - """Clear the output of the current cell receiving output. - - Parameters - ---------- - wait : bool [default: false] - Wait to clear the output until new output is available to replace it.""" - from IPython.core.interactiveshell import InteractiveShell - 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() diff --git a/contrib/python/ipython/py3/IPython/core/display_trap.py b/contrib/python/ipython/py3/IPython/core/display_trap.py deleted file mode 100644 index 9931dfe2df..0000000000 --- a/contrib/python/ipython/py3/IPython/core/display_trap.py +++ /dev/null @@ -1,70 +0,0 @@ -# encoding: utf-8 -""" -A context manager for handling sys.displayhook. - -Authors: - -* Robert Kern -* Brian Granger -""" - -#----------------------------------------------------------------------------- -# Copyright (C) 2008-2011 The IPython Development Team -# -# Distributed under the terms of the BSD License. The full license is in -# the file COPYING, distributed as part of this software. -#----------------------------------------------------------------------------- - -#----------------------------------------------------------------------------- -# Imports -#----------------------------------------------------------------------------- - -import sys - -from traitlets.config.configurable import Configurable -from traitlets import Any - -#----------------------------------------------------------------------------- -# Classes and functions -#----------------------------------------------------------------------------- - - -class DisplayTrap(Configurable): - """Object to manage sys.displayhook. - - This came from IPython.core.kernel.display_hook, but is simplified - (no callbacks or formatters) until more of the core is refactored. - """ - - hook = Any() - - def __init__(self, hook=None): - super(DisplayTrap, self).__init__(hook=hook, config=None) - self.old_hook = None - # We define this to track if a single BuiltinTrap is nested. - # Only turn off the trap when the outermost call to __exit__ is made. - self._nested_level = 0 - - def __enter__(self): - if self._nested_level == 0: - self.set() - self._nested_level += 1 - return self - - def __exit__(self, type, value, traceback): - if self._nested_level == 1: - self.unset() - self._nested_level -= 1 - # Returning False will cause exceptions to propagate - return False - - def set(self): - """Set the hook.""" - if sys.displayhook is not self.hook: - self.old_hook = sys.displayhook - sys.displayhook = self.hook - - def unset(self): - """Unset the hook.""" - sys.displayhook = self.old_hook - diff --git a/contrib/python/ipython/py3/IPython/core/displayhook.py b/contrib/python/ipython/py3/IPython/core/displayhook.py deleted file mode 100644 index 578e783ab8..0000000000 --- a/contrib/python/ipython/py3/IPython/core/displayhook.py +++ /dev/null @@ -1,325 +0,0 @@ -# -*- coding: utf-8 -*- -"""Displayhook for IPython. - -This defines a callable class that IPython uses for `sys.displayhook`. -""" - -# Copyright (c) IPython Development Team. -# Distributed under the terms of the Modified BSD License. - -import builtins as builtin_mod -import sys -import io as _io -import tokenize - -from traitlets.config.configurable import Configurable -from traitlets import Instance, Float -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 -# only and the other objects should ask that one object for their values. - -class DisplayHook(Configurable): - """The custom IPython displayhook to replace sys.displayhook. - - This class does many things, but the basic idea is that it is a callable - that gets called anytime user code returns a value. - """ - - shell = Instance('IPython.core.interactiveshell.InteractiveShellABC', - allow_none=True) - exec_result = Instance('IPython.core.interactiveshell.ExecutionResult', - allow_none=True) - cull_fraction = Float(0.2) - - def __init__(self, shell=None, cache_size=1000, **kwargs): - super(DisplayHook, self).__init__(shell=shell, **kwargs) - cache_size_min = 3 - if cache_size <= 0: - self.do_full_cache = 0 - cache_size = 0 - elif cache_size < cache_size_min: - self.do_full_cache = 0 - cache_size = 0 - warn('caching was disabled (min value for cache size is %s).' % - cache_size_min,stacklevel=3) - else: - self.do_full_cache = 1 - - self.cache_size = cache_size - - # we need a reference to the user-level namespace - self.shell = shell - - self._,self.__,self.___ = '','','' - - # these are deliberately global: - to_user_ns = {'_':self._,'__':self.__,'___':self.___} - self.shell.user_ns.update(to_user_ns) - - @property - def prompt_count(self): - return self.shell.execution_count - - #------------------------------------------------------------------------- - # Methods used in __call__. Override these methods to modify the behavior - # of the displayhook. - #------------------------------------------------------------------------- - - def check_for_underscore(self): - """Check if the user has set the '_' variable by hand.""" - # If something injected a '_' variable in __builtin__, delete - # ipython's automatic one so we don't clobber that. gettext() in - # particular uses _, so we need to stay away from it. - if '_' in builtin_mod.__dict__: - try: - user_value = self.shell.user_ns['_'] - if user_value is not self._: - return - del self.shell.user_ns['_'] - except KeyError: - pass - - def quiet(self): - """Should we silence the display hook because of ';'?""" - # do not print output if input ends in ';' - - try: - cell = self.shell.history_manager.input_hist_parsed[-1] - except IndexError: - # some uses of ipshellembed may fail here - return False - - sio = _io.StringIO(cell) - tokens = list(tokenize.generate_tokens(sio.readline)) - - for token in reversed(tokens): - if token[0] in (tokenize.ENDMARKER, tokenize.NL, tokenize.NEWLINE, tokenize.COMMENT): - continue - if (token[0] == tokenize.OP) and (token[1] == ';'): - return True - else: - return False - - def start_displayhook(self): - """Start the displayhook, initializing resources.""" - pass - - def write_output_prompt(self): - """Write the output prompt. - - The default implementation simply writes the prompt to - ``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) - if self.do_full_cache: - sys.stdout.write(outprompt) - - def compute_format_data(self, result): - """Compute format data of the object to be displayed. - - The format data is a generalization of the :func:`repr` of an object. - In the default implementation the format data is a :class:`dict` of - key value pair where the keys are valid MIME types and the values - are JSON'able data structure containing the raw data for that MIME - type. It is up to frontends to determine pick a MIME to to use and - display that data in an appropriate manner. - - This method only computes the format data for the object and should - NOT actually print or write that to a stream. - - Parameters - ---------- - result : object - The Python object passed to the display hook, whose format will be - computed. - - Returns - ------- - (format_dict, md_dict) : dict - format_dict is a :class:`dict` whose keys are valid MIME types and values are - JSON'able raw data for that MIME type. It is recommended that - all return values of this should always include the "text/plain" - MIME type representation of the object. - md_dict is a :class:`dict` with the same MIME type keys - of metadata associated with each output. - - """ - 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 - - def write_format_data(self, format_dict, md_dict=None) -> 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 - override this method to send the entire `format_dict` to the - frontends. - - Parameters - ---------- - format_dict : dict - The format dict for the object passed to `sys.displayhook`. - md_dict : dict (optional) - The metadata dict to be associated with the display data. - """ - if 'text/plain' not in format_dict: - # nothing to do - return - # We want to print because we want to always make sure we have a - # newline, even if all the prompt separators are ''. This is the - # standard IPython behavior. - result_repr = format_dict['text/plain'] - if '\n' in result_repr: - # So that multi-line strings line up with the left column of - # the screen, instead of having the output prompt mess up - # their first line. - # We use the prompt template instead of the expanded prompt - # 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: - # But avoid extraneous empty lines. - result_repr = '\n' + result_repr - - try: - print(result_repr) - except UnicodeEncodeError: - # If a character is not supported by the terminal encoding replace - # it with its \u or \x representation - print(result_repr.encode(sys.stdout.encoding,'backslashreplace').decode(sys.stdout.encoding)) - - def update_user_ns(self, result): - """Update user_ns with various things like _, __, _1, etc.""" - - # Avoid recursive reference when displaying _oh/Out - if self.cache_size and result is not self.shell.user_ns['_oh']: - if len(self.shell.user_ns['_oh']) >= self.cache_size and self.do_full_cache: - self.cull_cache() - - # Don't overwrite '_' and friends if '_' is in __builtin__ - # (otherwise we cause buggy behavior for things like gettext). and - # do not overwrite _, __ or ___ if one of these has been assigned - # by the user. - update_unders = True - for unders in ['_'*i for i in range(1,4)]: - if not unders in self.shell.user_ns: - continue - if getattr(self, unders) is not self.shell.user_ns.get(unders): - update_unders = False - - self.___ = self.__ - self.__ = self._ - self._ = result - - if ('_' not in builtin_mod.__dict__) and (update_unders): - self.shell.push({'_':self._, - '__':self.__, - '___':self.___}, interactive=False) - - # hackish access to top-level namespace to create _1,_2... dynamically - to_main = {} - if self.do_full_cache: - new_result = '_%s' % self.prompt_count - to_main[new_result] = result - self.shell.push(to_main, interactive=False) - self.shell.user_ns['_oh'][self.prompt_count] = result - - def fill_exec_result(self, result): - if self.exec_result is not None: - self.exec_result.result = result - - def log_output(self, format_dict): - """Log the output.""" - if 'text/plain' not in format_dict: - # nothing to do - return - if self.shell.logger.log_output: - self.shell.logger.log_write(format_dict['text/plain'], 'output') - self.shell.history_manager.output_hist_reprs[self.prompt_count] = \ - format_dict['text/plain'] - - def finish_displayhook(self): - """Finish up all displayhook activities.""" - sys.stdout.write(self.shell.separate_out2) - sys.stdout.flush() - - def __call__(self, result=None): - """Printing with history cache management. - - This is invoked every time the interpreter needs to print, and is - activated by setting the variable sys.displayhook to it. - """ - self.check_for_underscore() - if result is not None and not self.quiet(): - self.start_displayhook() - self.write_output_prompt() - format_dict, md_dict = self.compute_format_data(result) - self.update_user_ns(result) - self.fill_exec_result(result) - if format_dict: - self.write_format_data(format_dict, md_dict) - self.log_output(format_dict) - self.finish_displayhook() - - def cull_cache(self): - """Output cache is full, cull the oldest entries""" - oh = self.shell.user_ns.get('_oh', {}) - sz = len(oh) - cull_count = max(int(sz * self.cull_fraction), 2) - warn('Output cache limit (currently {sz} entries) hit.\n' - 'Flushing oldest {cull_count} entries.'.format(sz=sz, cull_count=cull_count)) - - for i, n in enumerate(sorted(oh)): - if i >= cull_count: - break - self.shell.user_ns.pop('_%i' % n, None) - oh.pop(n, None) - - - def flush(self): - if not self.do_full_cache: - raise ValueError("You shouldn't have reached the cache flush " - "if full caching is not enabled!") - # delete auto-generated vars from global namespace - - for n in range(1,self.prompt_count + 1): - key = '_'+repr(n) - try: - del self.shell.user_ns[key] - except: pass - # In some embedded circumstances, the user_ns doesn't have the - # '_oh' key set up. - oh = self.shell.user_ns.get('_oh', None) - if oh is not None: - oh.clear() - - # Release our own references to objects: - self._, self.__, self.___ = '', '', '' - - if '_' not in builtin_mod.__dict__: - self.shell.user_ns.update({'_':self._,'__':self.__,'___':self.___}) - import gc - # TODO: Is this really needed? - # IronPython blocks here forever - if sys.platform != "cli": - gc.collect() - - -class CapturingDisplayHook(object): - def __init__(self, shell, outputs=None): - self.shell = shell - if outputs is None: - outputs = [] - self.outputs = outputs - - def __call__(self, result=None): - if result is None: - return - format_dict, md_dict = self.shell.display_formatter.format(result) - self.outputs.append({ 'data': format_dict, 'metadata': md_dict }) diff --git a/contrib/python/ipython/py3/IPython/core/displaypub.py b/contrib/python/ipython/py3/IPython/core/displaypub.py deleted file mode 100644 index 74028ec79e..0000000000 --- a/contrib/python/ipython/py3/IPython/core/displaypub.py +++ /dev/null @@ -1,138 +0,0 @@ -"""An interface for publishing rich data to frontends. - -There are two components of the display system: - -* Display formatters, which take a Python object and compute the - representation of the object in various formats (text, HTML, SVG, etc.). -* The display publisher that is used to send the representation data to the - various frontends. - -This module defines the logic display publishing. The display publisher uses -the ``display_data`` message type that is defined in the IPython messaging -spec. -""" - -# Copyright (c) IPython Development Team. -# Distributed under the terms of the Modified BSD License. - - -import sys - -from traitlets.config.configurable import Configurable -from traitlets import List - -# This used to be defined here - it is imported for backwards compatibility -from .display_functions import publish_display_data - -#----------------------------------------------------------------------------- -# Main payload class -#----------------------------------------------------------------------------- - - -class DisplayPublisher(Configurable): - """A traited class that publishes display data to frontends. - - Instances of this class are created by the main IPython object and should - be accessed there. - """ - - def __init__(self, shell=None, *args, **kwargs): - self.shell = shell - super().__init__(*args, **kwargs) - - def _validate_data(self, data, metadata=None): - """Validate the display data. - - Parameters - ---------- - data : dict - The formata data dictionary. - metadata : dict - Any metadata for the data. - """ - - if not isinstance(data, dict): - raise TypeError('data must be a dict, got: %r' % data) - if metadata is not None: - if not isinstance(metadata, dict): - raise TypeError('metadata must be a dict, got: %r' % data) - - # use * to indicate transient, update are keyword-only - def publish(self, data, metadata=None, source=None, *, transient=None, update=False, **kwargs) -> None: - """Publish data and metadata to all frontends. - - See the ``display_data`` message in the messaging documentation for - more details about this message type. - - The following MIME types are currently implemented: - - * text/plain - * text/html - * text/markdown - * text/latex - * application/json - * application/javascript - * image/png - * image/jpeg - * image/svg+xml - - Parameters - ---------- - data : dict - A dictionary having keys that are valid MIME types (like - 'text/plain' or 'image/svg+xml') and values that are the data for - that MIME type. The data itself must be a JSON'able data - structure. Minimally all data should have the 'text/plain' data, - which can be displayed by all frontends. If more than the plain - text is given, it is up to the frontend to decide which - representation to use. - metadata : dict - A dictionary for metadata related to the data. This can contain - arbitrary key, value pairs that frontends can use to interpret - the data. Metadata specific to each mime-type can be specified - in the metadata dict with the same mime-type keys as - the data itself. - source : str, deprecated - Unused. - transient : dict, keyword-only - A dictionary for transient data. - Data in this dictionary should not be persisted as part of saving this output. - Examples include 'display_id'. - update : bool, keyword-only, default: False - If True, only update existing outputs with the same display_id, - rather than creating a new output. - """ - - handlers = {} - if self.shell is not None: - handlers = getattr(self.shell, 'mime_renderers', {}) - - for mime, handler in handlers.items(): - if mime in data: - handler(data[mime], metadata.get(mime, None)) - return - - if 'text/plain' in data: - 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() - - -class CapturingDisplayPublisher(DisplayPublisher): - """A DisplayPublisher that stores""" - outputs = List() - - def publish(self, data, metadata=None, source=None, *, transient=None, update=False): - self.outputs.append({'data':data, 'metadata':metadata, - 'transient':transient, 'update':update}) - - def clear_output(self, wait=False): - super(CapturingDisplayPublisher, self).clear_output(wait) - - # empty the list, *do not* reassign a new list - self.outputs.clear() diff --git a/contrib/python/ipython/py3/IPython/core/error.py b/contrib/python/ipython/py3/IPython/core/error.py deleted file mode 100644 index 684cbc8da6..0000000000 --- a/contrib/python/ipython/py3/IPython/core/error.py +++ /dev/null @@ -1,60 +0,0 @@ -# encoding: utf-8 -""" -Global exception classes for IPython.core. - -Authors: - -* Brian Granger -* Fernando Perez -* Min Ragan-Kelley - -Notes ------ -""" - -#----------------------------------------------------------------------------- -# Copyright (C) 2008 The IPython Development Team -# -# Distributed under the terms of the BSD License. The full license is in -# the file COPYING, distributed as part of this software. -#----------------------------------------------------------------------------- - -#----------------------------------------------------------------------------- -# Imports -#----------------------------------------------------------------------------- - -#----------------------------------------------------------------------------- -# Exception classes -#----------------------------------------------------------------------------- - -class IPythonCoreError(Exception): - pass - - -class TryNext(IPythonCoreError): - """Try next hook exception. - - Raise this in your hook function to indicate that the next hook handler - should be used to handle the operation. - """ - -class UsageError(IPythonCoreError): - """Error in magic function arguments, etc. - - Something that probably won't warrant a full traceback, but should - nevertheless interrupt a macro / batch file. - """ - -class StdinNotImplementedError(IPythonCoreError, NotImplementedError): - """raw_input was requested in a context where it is not supported - - For use in IPython kernels, where only some frontends may support - stdin requests. - """ - -class InputRejected(Exception): - """Input rejected by ast transformer. - - Raise this in your NodeTransformer to indicate that InteractiveShell should - not execute the supplied input. - """ diff --git a/contrib/python/ipython/py3/IPython/core/events.py b/contrib/python/ipython/py3/IPython/core/events.py deleted file mode 100644 index 73fc181ae5..0000000000 --- a/contrib/python/ipython/py3/IPython/core/events.py +++ /dev/null @@ -1,161 +0,0 @@ -"""Infrastructure for registering and firing callbacks on application events. - -Unlike :mod:`IPython.core.hooks`, which lets end users set single functions to -be called at specific times, or a collection of alternative methods to try, -callbacks are designed to be used by extension authors. A number of callbacks -can be registered for the same event without needing to be aware of one another. - -The functions defined in this module are no-ops indicating the names of available -events and the arguments which will be passed to them. - -.. note:: - - This API is experimental in IPython 2.0, and may be revised in future versions. -""" - -from backcall import callback_prototype - - -class EventManager(object): - """Manage a collection of events and a sequence of callbacks for each. - - This is attached to :class:`~IPython.core.interactiveshell.InteractiveShell` - instances as an ``events`` attribute. - - .. note:: - - This API is experimental in IPython 2.0, and may be revised in future versions. - """ - def __init__(self, shell, available_events): - """Initialise the :class:`CallbackManager`. - - Parameters - ---------- - shell - The :class:`~IPython.core.interactiveshell.InteractiveShell` instance - available_events - An iterable of names for callback events. - """ - self.shell = shell - self.callbacks = {n:[] for n in available_events} - - def register(self, event, function): - """Register a new event callback. - - Parameters - ---------- - event : str - The event for which to register this callback. - function : callable - A function to be called on the given event. It should take the same - parameters as the appropriate callback prototype. - - Raises - ------ - TypeError - If ``function`` is not callable. - KeyError - If ``event`` is not one of the known events. - """ - if not callable(function): - raise TypeError('Need a callable, got %r' % function) - callback_proto = available_events.get(event) - if function not in self.callbacks[event]: - self.callbacks[event].append(callback_proto.adapt(function)) - - def unregister(self, event, function): - """Remove a callback from the given event.""" - if function in self.callbacks[event]: - return self.callbacks[event].remove(function) - - # Remove callback in case ``function`` was adapted by `backcall`. - for callback in self.callbacks[event]: - try: - if callback.__wrapped__ is function: - return self.callbacks[event].remove(callback) - except AttributeError: - pass - - raise ValueError('Function {!r} is not registered as a {} callback'.format(function, event)) - - def trigger(self, event, *args, **kwargs): - """Call callbacks for ``event``. - - 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][:]: - try: - func(*args, **kwargs) - except (Exception, KeyboardInterrupt): - print("Error in callback {} (for {}):".format(func, event)) - self.shell.showtraceback() - -# event_name -> prototype mapping -available_events = {} - -def _define_event(callback_function): - callback_proto = callback_prototype(callback_function) - available_events[callback_function.__name__] = callback_proto - return callback_proto - -# ------------------------------------------------------------------------------ -# Callback prototypes -# -# No-op functions which describe the names of available events and the -# signatures of callbacks for those events. -# ------------------------------------------------------------------------------ - -@_define_event -def pre_execute(): - """Fires before code is executed in response to user/frontend action. - - This includes comm and widget messages and silent execution, as well as user - code cells. - """ - pass - -@_define_event -def pre_run_cell(info): - """Fires before user-entered code runs. - - Parameters - ---------- - info : :class:`~IPython.core.interactiveshell.ExecutionInfo` - An object containing information used for the code execution. - """ - pass - -@_define_event -def post_execute(): - """Fires after code is executed in response to user/frontend action. - - This includes comm and widget messages and silent execution, as well as user - code cells. - """ - pass - -@_define_event -def post_run_cell(result): - """Fires after user-entered code runs. - - Parameters - ---------- - result : :class:`~IPython.core.interactiveshell.ExecutionResult` - The object which will be returned as the execution result. - """ - pass - -@_define_event -def shell_initialized(ip): - """Fires after initialisation of :class:`~IPython.core.interactiveshell.InteractiveShell`. - - This is before extensions and startup scripts are loaded, so it can only be - set by subclassing. - - Parameters - ---------- - ip : :class:`~IPython.core.interactiveshell.InteractiveShell` - The newly initialised shell. - """ - pass diff --git a/contrib/python/ipython/py3/IPython/core/excolors.py b/contrib/python/ipython/py3/IPython/core/excolors.py deleted file mode 100644 index c47ce922c4..0000000000 --- a/contrib/python/ipython/py3/IPython/core/excolors.py +++ /dev/null @@ -1,166 +0,0 @@ -# -*- coding: utf-8 -*- -""" -Color schemes for exception handling code in IPython. -""" - -import os -import warnings - -#***************************************************************************** -# Copyright (C) 2005-2006 Fernando Perez <fperez@colorado.edu> -# -# Distributed under the terms of the BSD License. The full license is in -# the file COPYING, distributed as part of this software. -#***************************************************************************** - -from IPython.utils.coloransi import ColorSchemeTable, TermColors, ColorScheme - -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 - in. - - Examples: - - >>> ec = exception_colors() - >>> ec.active_scheme_name - '' - >>> print(ec.active_colors) - None - - Now we activate a color scheme: - >>> ec.set_active_scheme('NoColor') - >>> ec.active_scheme_name - 'NoColor' - >>> sorted(ec.active_colors.keys()) - ['Normal', 'caret', 'em', 'excName', 'filename', 'filenameEm', 'line', - 'lineno', 'linenoEm', 'name', 'nameEm', 'normalEm', 'topline', 'vName', - 'val', 'valEm'] - """ - - ex_colors = ColorSchemeTable() - - # Populate it with color schemes - C = TermColors # shorthand and local lookup - ex_colors.add_scheme(ColorScheme( - 'NoColor', - # The color to be used for the top line - topline = C.NoColor, - - # The colors to be used in the traceback - filename = C.NoColor, - lineno = C.NoColor, - name = C.NoColor, - vName = C.NoColor, - val = C.NoColor, - em = C.NoColor, - - # Emphasized colors for the last frame of the traceback - normalEm = C.NoColor, - filenameEm = C.NoColor, - linenoEm = C.NoColor, - nameEm = C.NoColor, - valEm = C.NoColor, - - # Colors for printing the exception - excName = C.NoColor, - line = C.NoColor, - caret = C.NoColor, - Normal = C.NoColor - )) - - # make some schemes as instances so we can copy them for modification easily - ex_colors.add_scheme(ColorScheme( - 'Linux', - # The color to be used for the top line - topline = C.LightRed, - - # The colors to be used in the traceback - filename = C.Green, - lineno = C.Green, - name = C.Purple, - vName = C.Cyan, - val = C.Green, - em = C.LightCyan, - - # Emphasized colors for the last frame of the traceback - normalEm = C.LightCyan, - filenameEm = C.LightGreen, - linenoEm = C.LightGreen, - nameEm = C.LightPurple, - valEm = C.LightBlue, - - # Colors for printing the exception - excName = C.LightRed, - line = C.Yellow, - caret = C.White, - Normal = C.Normal - )) - - # For light backgrounds, swap dark/light colors - ex_colors.add_scheme(ColorScheme( - 'LightBG', - # 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 diff --git a/contrib/python/ipython/py3/IPython/core/extensions.py b/contrib/python/ipython/py3/IPython/core/extensions.py deleted file mode 100644 index 4ca266869c..0000000000 --- a/contrib/python/ipython/py3/IPython/core/extensions.py +++ /dev/null @@ -1,167 +0,0 @@ -# encoding: utf-8 -"""A class for managing IPython extensions.""" - -# Copyright (c) IPython Development Team. -# Distributed under the terms of the Modified BSD License. - -import os -import os.path -import sys -from importlib import import_module, reload - -from traitlets.config.configurable import Configurable -from IPython.utils.path import ensure_dir_exists, compress_user -from IPython.utils.decorators import undoc -from traitlets import Instance - - -#----------------------------------------------------------------------------- -# Main class -#----------------------------------------------------------------------------- - -BUILTINS_EXTS = {"storemagic": False, "autoreload": False} - - -class ExtensionManager(Configurable): - """A class to manage IPython extensions. - - An IPython extension is an importable Python module that has - a function with the signature:: - - def load_ipython_extension(ipython): - # Do things with ipython - - This function is called after your extension is imported and the - currently active :class:`InteractiveShell` instance is passed as - 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 - if the extension is reloaded. - - You can put your extension modules anywhere you want, as long as - they can be imported by Python's standard import mechanism. However, - to make it easy to write extensions, you can also put your extensions - in ``os.path.join(self.ipython_dir, 'extensions')``. This directory - is added to ``sys.path`` automatically. - """ - - 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.loaded = set() - - @property - def ipython_extension_dir(self): - return os.path.join(self.shell.ipython_dir, u'extensions') - - def _on_ipython_dir_changed(self, change): - ensure_dir_exists(self.ipython_extension_dir) - - def load_extension(self, module_str: str): - """Load an IPython extension by its module name. - - Returns the string "already loaded" if the extension is already loaded, - "no load function" if the module doesn't have a load_ipython_extension - function, or None if it succeeded. - """ - try: - return self._load_extension(module_str) - except ModuleNotFoundError: - if module_str in BUILTINS_EXTS: - BUILTINS_EXTS[module_str] = True - return self._load_extension("IPython.extensions." + module_str) - raise - - def _load_extension(self, module_str: str): - if module_str in self.loaded: - return "already loaded" - - with self.shell.builtin_trap: - if module_str not in sys.modules: - try: - sys.modules[module_str] = __import__('IPython.extensions.' + module_str) - except ImportError: - mod = import_module(module_str) - if mod.__file__.startswith(self.ipython_extension_dir): - print(("Loading extensions from {dir} is deprecated. " - "We recommend managing extensions like any " - "other Python packages, in site-packages.").format( - dir=compress_user(self.ipython_extension_dir))) - mod = sys.modules[module_str] - if self._call_load_ipython_extension(mod): - self.loaded.add(module_str) - else: - return "no load function" - - def unload_extension(self, module_str: str): - """Unload an IPython extension by its module name. - - 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 BUILTINS_EXTS.get(module_str, False) is True: - module_str = "IPython.extensions." + module_str - 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): - self.loaded.discard(module_str) - else: - return "no unload function" - - def reload_extension(self, module_str: str): - """Reload an IPython extension by calling reload. - - If the module has not been loaded before, - :meth:`InteractiveShell.load_extension` is called. Otherwise - :func:`reload` is called and then the :func:`load_ipython_extension` - function of the module, if it exists is called. - """ - from IPython.utils.syspathcontext import prepended_to_syspath - - if BUILTINS_EXTS.get(module_str, False) is True: - module_str = "IPython.extensions." + module_str - - if (module_str in self.loaded) and (module_str in sys.modules): - self.unload_extension(module_str) - mod = sys.modules[module_str] - with prepended_to_syspath(self.ipython_extension_dir): - reload(mod) - if self._call_load_ipython_extension(mod): - self.loaded.add(module_str) - else: - self.load_extension(module_str) - - def _call_load_ipython_extension(self, mod): - if hasattr(mod, 'load_ipython_extension'): - mod.load_ipython_extension(self.shell) - return True - - def _call_unload_ipython_extension(self, mod): - if hasattr(mod, 'unload_ipython_extension'): - mod.unload_ipython_extension(self.shell) - return True - - @undoc - def install_extension(self, url, filename=None): - """ - Deprecated. - """ - # Ensure the extension directory exists - raise DeprecationWarning( - '`install_extension` and the `install_ext` magic have been deprecated since IPython 4.0' - 'Use pip or other package managers to manage ipython extensions.') diff --git a/contrib/python/ipython/py3/IPython/core/formatters.py b/contrib/python/ipython/py3/IPython/core/formatters.py deleted file mode 100644 index 4e0b9e455a..0000000000 --- a/contrib/python/ipython/py3/IPython/core/formatters.py +++ /dev/null @@ -1,1027 +0,0 @@ -# -*- coding: utf-8 -*- -"""Display formatters. - -Inheritance diagram: - -.. inheritance-diagram:: IPython.core.formatters - :parts: 3 -""" - -# Copyright (c) IPython Development Team. -# Distributed under the terms of the Modified BSD License. - -import abc -import json -import sys -import traceback -import warnings -from io import StringIO - -from decorator import decorator - -from traitlets.config.configurable import Configurable -from .getipython import get_ipython -from ..utils.sentinel import Sentinel -from ..utils.dir2 import get_real_method -from ..lib import pretty -from traitlets import ( - Bool, Dict, Integer, Unicode, CUnicode, ObjectName, List, - ForwardDeclaredInstance, - default, observe, -) - - -class DisplayFormatter(Configurable): - - 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') - def _active_types_default(self): - return self.format_types - - @observe('active_types') - def _active_types_changed(self, change): - for key, formatter in self.formatters.items(): - 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): - return IPythonDisplayFormatter(parent=self) - - mimebundle_formatter = ForwardDeclaredInstance('FormatterABC') - @default('mimebundle_formatter') - def _default_mime_formatter(self): - return MimeBundleFormatter(parent=self) - - # A dict of formatter whose keys are format types (MIME types) and whose - # values are subclasses of BaseFormatter. - formatters = Dict() - @default('formatters') - def _formatters_default(self): - """Activate the default formatters.""" - formatter_classes = [ - PlainTextFormatter, - HTMLFormatter, - MarkdownFormatter, - SVGFormatter, - PNGFormatter, - PDFFormatter, - JPEGFormatter, - LatexFormatter, - JSONFormatter, - JavascriptFormatter - ] - d = {} - for cls in formatter_classes: - f = cls(parent=self) - d[f.format_type] = f - return d - - def format(self, obj, include=None, exclude=None): - """Return a format data dict for an object. - - By default all format types will be computed. - - The following MIME types are usually implemented: - - * text/plain - * text/html - * text/markdown - * text/latex - * application/json - * application/javascript - * application/pdf - * image/png - * image/jpeg - * image/svg+xml - - Parameters - ---------- - obj : object - The Python object whose format data will be computed. - include : list, tuple or set; optional - A list of format type strings (MIME types) to include in the - format data dict. If this is set *only* the format types included - in this list will be computed. - exclude : list, tuple or set; optional - A list of format type string (MIME types) to exclude in the format - data dict. If this is set all format types will be computed, - except for those included in this argument. - Mimetypes present in exclude will take precedence over the ones in include - - Returns - ------- - (format_dict, metadata_dict) : tuple of two dicts - format_dict is a dictionary of key/value pairs, one of each format that was - generated for the object. The keys are the format types, which - will usually be MIME type strings and the values and JSON'able - data structure containing the raw data for the representation in - that format. - - metadata_dict is a dictionary of metadata about each mime-type output. - Its keys will be a strict subset of the keys in format_dict. - - Notes - ----- - If an object implement `_repr_mimebundle_` as well as various - `_repr_*_`, the data returned by `_repr_mimebundle_` will take - precedence and the corresponding `_repr_*_` for this mimetype will - not be called. - - """ - format_dict = {} - md_dict = {} - - if self.ipython_display_formatter(obj): - # object handled itself, don't proceed - return {}, {} - - format_dict, md_dict = self.mimebundle_formatter(obj, include=include, exclude=exclude) - - if format_dict or md_dict: - if include: - format_dict = {k:v for k,v in format_dict.items() if k in include} - md_dict = {k:v for k,v in md_dict.items() if k in include} - if exclude: - format_dict = {k:v for k,v in format_dict.items() if k not in exclude} - md_dict = {k:v for k,v in md_dict.items() if k not in exclude} - - for format_type, formatter in self.formatters.items(): - if format_type in format_dict: - # already got it from mimebundle, maybe don't render again. - # exception: manually registered per-mime renderer - # check priority: - # 1. user-registered per-mime formatter - # 2. mime-bundle (user-registered or repr method) - # 3. default per-mime formatter (e.g. repr method) - try: - formatter.lookup(obj) - except KeyError: - # no special formatter, use mime-bundle-provided value - continue - if include and format_type not in include: - continue - if exclude and format_type in exclude: - continue - - md = None - try: - data = formatter(obj) - except: - # FIXME: log the exception - raise - - # formatters can return raw data or (data, metadata) - if isinstance(data, tuple) and len(data) == 2: - data, md = data - - if data is not None: - format_dict[format_type] = data - if md is not None: - md_dict[format_type] = md - return format_dict, md_dict - - @property - def format_types(self): - """Return the format types (MIME types) of the active formatters.""" - return list(self.formatters.keys()) - - -#----------------------------------------------------------------------------- -# Formatters for specific format types (text, html, svg, etc.) -#----------------------------------------------------------------------------- - - -def _safe_repr(obj): - """Try to return a repr of an object - - always returns a string, at least. - """ - try: - return repr(obj) - except Exception as e: - return "un-repr-able object (%r)" % e - - -class FormatterWarning(UserWarning): - """Warning class for errors in formatters""" - -@decorator -def catch_format_error(method, self, *args, **kwargs): - """show traceback on failed format call""" - try: - r = method(self, *args, **kwargs) - except NotImplementedError: - # don't warn on NotImplementedErrors - return self._check_return(None, args[0]) - except Exception: - exc_info = sys.exc_info() - ip = get_ipython() - if ip is not None: - ip.showtraceback(exc_info) - else: - traceback.print_exception(*exc_info) - return self._check_return(None, args[0]) - return self._check_return(r, args[0]) - - -class FormatterABC(metaclass=abc.ABCMeta): - """ Abstract base class for Formatters. - - A formatter is a callable class that is responsible for computing the - raw format data for a particular format type (MIME type). For example, - an HTML formatter would have a format type of `text/html` and would return - the HTML representation of the object when called. - """ - - # The format type of the data returned, usually a MIME type. - format_type = 'text/plain' - - # Is the formatter enabled... - enabled = True - - @abc.abstractmethod - def __call__(self, obj): - """Return a JSON'able representation of the object. - - If the object cannot be formatted by this formatter, - warn and return None. - """ - return repr(obj) - - -def _mod_name_key(typ): - """Return a (__module__, __name__) tuple for a type. - - Used as key in Formatter.deferred_printers. - """ - module = getattr(typ, '__module__', None) - name = getattr(typ, '__name__', None) - return (module, name) - - -def _get_type(obj): - """Return the type of an instance (old and new-style)""" - return getattr(obj, '__class__', None) or type(obj) - - -_raise_key_error = Sentinel('_raise_key_error', __name__, -""" -Special value to raise a KeyError - -Raise KeyError in `BaseFormatter.pop` if passed as the default value to `pop` -""") - - -class BaseFormatter(Configurable): - """A base formatter class that is configurable. - - This formatter should usually be used as the base class of all formatters. - It is a traited :class:`Configurable` class and includes an extensible - API for users to determine how their objects are formatted. The following - logic is used to find a function to format an given object. - - 1. The object is introspected to see if it has a method with the name - :attr:`print_method`. If is does, that object is passed to that method - for formatting. - 2. If no print method is found, three internal dictionaries are consulted - to find print method: :attr:`singleton_printers`, :attr:`type_printers` - and :attr:`deferred_printers`. - - Users should use these dictionaries to register functions that will be - used to compute the format data for their objects (if those objects don't - have the special print methods). The easiest way of using these - dictionaries is through the :meth:`for_type` and :meth:`for_type_by_name` - methods. - - If no function/callable is found to compute the format data, ``None`` is - returned and this format type is not used. - """ - - format_type = Unicode('text/plain') - _return_type = str - - 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) - - # The type-specific printers. - # Map type objects to the format functions. - 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) - - @catch_format_error - def __call__(self, obj): - """Compute the format for an object.""" - if self.enabled: - # lookup registered printer - try: - printer = self.lookup(obj) - except KeyError: - pass - else: - return printer(obj) - # Finally look for special method names - method = get_real_method(obj, self.print_method) - if method is not None: - return method() - return None - else: - return None - - def __contains__(self, typ): - """map in to lookup_by_type""" - try: - self.lookup_by_type(typ) - except KeyError: - return False - else: - return True - - def _check_return(self, r, obj): - """Check that a return value is appropriate - - Return the value if so, None otherwise, warning if invalid. - """ - if r is None or isinstance(r, self._return_type) or \ - (isinstance(r, tuple) and r and isinstance(r[0], self._return_type)): - return r - else: - warnings.warn( - "%s formatter returned invalid type %s (expected %s) for object: %s" % \ - (self.format_type, type(r), self._return_type, _safe_repr(obj)), - FormatterWarning - ) - - def lookup(self, obj): - """Look up the formatter for a given instance. - - Parameters - ---------- - obj : object instance - - Returns - ------- - f : callable - The registered formatting callable for the type. - - Raises - ------ - KeyError if the type has not been registered. - """ - # look for singleton first - obj_id = id(obj) - if obj_id in self.singleton_printers: - return self.singleton_printers[obj_id] - # then lookup by type - return self.lookup_by_type(_get_type(obj)) - - def lookup_by_type(self, typ): - """Look up the registered formatter for a type. - - Parameters - ---------- - typ : type or '__module__.__name__' string for a type - - Returns - ------- - f : callable - The registered formatting callable for the type. - - Raises - ------ - KeyError if the type has not been registered. - """ - if isinstance(typ, str): - typ_key = tuple(typ.rsplit('.',1)) - if typ_key not in self.deferred_printers: - # We may have it cached in the type map. We will have to - # iterate over all of the types to check. - for cls in self.type_printers: - if _mod_name_key(cls) == typ_key: - return self.type_printers[cls] - else: - return self.deferred_printers[typ_key] - else: - for cls in pretty._get_mro(typ): - if cls in self.type_printers or self._in_deferred_types(cls): - return self.type_printers[cls] - - # If we have reached here, the lookup failed. - raise KeyError("No registered printer for {0!r}".format(typ)) - - def for_type(self, typ, func=None): - """Add a format function for a given type. - - Parameters - ---------- - typ : type or '__module__.__name__' string for a type - The class of the object that will be formatted using `func`. - - func : callable - A callable for computing the format data. - `func` will be called with the object to be formatted, - and will return the raw data in this formatter's format. - Subclasses may use a different call signature for the - `func` argument. - - If `func` is None or not specified, there will be no change, - only returning the current value. - - Returns - ------- - oldfunc : callable - The currently registered callable. - If you are registering a new formatter, - this will be the previous value (to enable restoring later). - """ - # if string given, interpret as 'pkg.module.class_name' - if isinstance(typ, str): - type_module, type_name = typ.rsplit('.', 1) - return self.for_type_by_name(type_module, type_name, func) - - try: - oldfunc = self.lookup_by_type(typ) - except KeyError: - oldfunc = None - - if func is not None: - self.type_printers[typ] = func - - return oldfunc - - def for_type_by_name(self, type_module, type_name, func=None): - """Add a format function for a type specified by the full dotted - module and name of the type, rather than the type of the object. - - Parameters - ---------- - type_module : str - The full dotted name of the module the type is defined in, like - ``numpy``. - - type_name : str - The name of the type (the class name), like ``dtype`` - - func : callable - A callable for computing the format data. - `func` will be called with the object to be formatted, - and will return the raw data in this formatter's format. - Subclasses may use a different call signature for the - `func` argument. - - If `func` is None or unspecified, there will be no change, - only returning the current value. - - Returns - ------- - oldfunc : callable - The currently registered callable. - If you are registering a new formatter, - this will be the previous value (to enable restoring later). - """ - key = (type_module, type_name) - - try: - oldfunc = self.lookup_by_type("%s.%s" % key) - except KeyError: - oldfunc = None - - if func is not None: - self.deferred_printers[key] = func - return oldfunc - - def pop(self, typ, default=_raise_key_error): - """Pop a formatter for the given type. - - Parameters - ---------- - typ : type or '__module__.__name__' string for a type - default : object - value to be returned if no formatter is registered for typ. - - Returns - ------- - obj : object - The last registered object for the type. - - Raises - ------ - KeyError if the type is not registered and default is not specified. - """ - - if isinstance(typ, str): - typ_key = tuple(typ.rsplit('.',1)) - if typ_key not in self.deferred_printers: - # We may have it cached in the type map. We will have to - # iterate over all of the types to check. - for cls in self.type_printers: - if _mod_name_key(cls) == typ_key: - old = self.type_printers.pop(cls) - break - else: - old = default - else: - old = self.deferred_printers.pop(typ_key) - else: - if typ in self.type_printers: - old = self.type_printers.pop(typ) - else: - old = self.deferred_printers.pop(_mod_name_key(typ), default) - if old is _raise_key_error: - raise KeyError("No registered value for {0!r}".format(typ)) - return old - - def _in_deferred_types(self, cls): - """ - Check if the given class is specified in the deferred type registry. - - Successful matches will be moved to the regular type registry for future use. - """ - mod = getattr(cls, '__module__', None) - name = getattr(cls, '__name__', None) - key = (mod, name) - if key in self.deferred_printers: - # Move the printer over to the regular registry. - printer = self.deferred_printers.pop(key) - self.type_printers[cls] = printer - return True - return False - - -class PlainTextFormatter(BaseFormatter): - """The default pretty-printer. - - This uses :mod:`IPython.lib.pretty` to compute the format data of - the object. If the object cannot be pretty printed, :func:`repr` is used. - See the documentation of :mod:`IPython.lib.pretty` for details on - how to write pretty printers. Here is a simple example:: - - def dtype_pprinter(obj, p, cycle): - if cycle: - return p.text('dtype(...)') - if hasattr(obj, 'fields'): - if obj.fields is None: - p.text(repr(obj)) - else: - p.begin_group(7, 'dtype([') - for i, field in enumerate(obj.descr): - if i > 0: - p.text(',') - p.breakable() - p.pretty(field) - p.end_group(7, '])') - """ - - # The format type of data returned. - format_type = Unicode('text/plain') - - # This subclass ignores this attribute as it always need to return - # something. - enabled = Bool(True).tag(config=False) - - 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) - - # 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) - - # Whether to be verbose or not. - verbose = Bool(False).tag(config=True) - - # The maximum width. - max_width = Integer(79).tag(config=True) - - # The newline character. - 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) - - @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. - This will set float_format, after interpreting input. - If numpy has been imported, numpy print precision will also be set. - - integer `n` sets format to '%.nf', otherwise, format set directly. - - An empty string returns to defaults (repr for float, 8 for numpy). - - This parameter can be set via the '%precision' magic. - """ - new = change['new'] - if '%' in new: - # got explicit format string - fmt = new - try: - fmt%3.14159 - except Exception as e: - raise ValueError("Precision must be int or format string, not %r"%new) from e - elif new: - # otherwise, should be an int - try: - i = int(new) - assert i >= 0 - except ValueError as e: - raise ValueError("Precision must be int or format string, not %r"%new) from e - except AssertionError as e: - raise ValueError("int precision must be non-negative, not %r"%i) from e - - fmt = '%%.%if'%i - if 'numpy' in sys.modules: - # set numpy precision if it has been imported - import numpy - numpy.set_printoptions(precision=i) - else: - # default back to repr - fmt = '%r' - if 'numpy' in sys.modules: - import numpy - # numpy default is 8 - numpy.set_printoptions(precision=8) - self.float_format = fmt - - # Use the default pretty printers from IPython.lib.pretty. - @default('singleton_printers') - def _singleton_printers_default(self): - return pretty._singleton_pprinters.copy() - - @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) - # if NumPy is used, set precision for its float64 type - if "numpy" in sys.modules: - import numpy - - d[numpy.float64] = lambda obj, p, cycle: p.text(self.float_format % obj) - return d - - @default('deferred_printers') - def _deferred_printers_default(self): - return pretty._deferred_type_pprinters.copy() - - #### FormatterABC interface #### - - @catch_format_error - def __call__(self, obj): - """Compute the pretty representation of the object.""" - if not self.pprint: - return repr(obj) - else: - stream = StringIO() - printer = pretty.RepresentationPrinter(stream, self.verbose, - self.max_width, self.newline, - max_seq_length=self.max_seq_length, - singleton_pprinters=self.singleton_printers, - type_pprinters=self.type_printers, - deferred_pprinters=self.deferred_printers) - printer.pretty(obj) - printer.flush() - return stream.getvalue() - - -class HTMLFormatter(BaseFormatter): - """An HTML formatter. - - To define the callables that compute the HTML representation of your - objects, define a :meth:`_repr_html_` method or use the :meth:`for_type` - or :meth:`for_type_by_name` methods to register functions that handle - this. - - The return value of this formatter should be a valid HTML snippet that - could be injected into an existing DOM. It should *not* include the - ```<html>`` or ```<body>`` tags. - """ - format_type = Unicode('text/html') - - print_method = ObjectName('_repr_html_') - - -class MarkdownFormatter(BaseFormatter): - """A Markdown formatter. - - To define the callables that compute the Markdown representation of your - objects, define a :meth:`_repr_markdown_` method or use the :meth:`for_type` - or :meth:`for_type_by_name` methods to register functions that handle - this. - - The return value of this formatter should be a valid Markdown. - """ - format_type = Unicode('text/markdown') - - print_method = ObjectName('_repr_markdown_') - -class SVGFormatter(BaseFormatter): - """An SVG formatter. - - To define the callables that compute the SVG representation of your - objects, define a :meth:`_repr_svg_` method or use the :meth:`for_type` - or :meth:`for_type_by_name` methods to register functions that handle - this. - - The return value of this formatter should be valid SVG enclosed in - ```<svg>``` tags, that could be injected into an existing DOM. It should - *not* include the ```<html>`` or ```<body>`` tags. - """ - format_type = Unicode('image/svg+xml') - - print_method = ObjectName('_repr_svg_') - - -class PNGFormatter(BaseFormatter): - """A PNG formatter. - - To define the callables that compute the PNG representation of your - objects, define a :meth:`_repr_png_` method or use the :meth:`for_type` - or :meth:`for_type_by_name` methods to register functions that handle - this. - - The return value of this formatter should be raw PNG data, *not* - base64 encoded. - """ - format_type = Unicode('image/png') - - print_method = ObjectName('_repr_png_') - - _return_type = (bytes, str) - - -class JPEGFormatter(BaseFormatter): - """A JPEG formatter. - - To define the callables that compute the JPEG representation of your - objects, define a :meth:`_repr_jpeg_` method or use the :meth:`for_type` - or :meth:`for_type_by_name` methods to register functions that handle - this. - - The return value of this formatter should be raw JPEG data, *not* - base64 encoded. - """ - format_type = Unicode('image/jpeg') - - print_method = ObjectName('_repr_jpeg_') - - _return_type = (bytes, str) - - -class LatexFormatter(BaseFormatter): - """A LaTeX formatter. - - To define the callables that compute the LaTeX representation of your - objects, define a :meth:`_repr_latex_` method or use the :meth:`for_type` - or :meth:`for_type_by_name` methods to register functions that handle - this. - - The return value of this formatter should be a valid LaTeX equation, - enclosed in either ```$```, ```$$``` or another LaTeX equation - environment. - """ - format_type = Unicode('text/latex') - - print_method = ObjectName('_repr_latex_') - - -class JSONFormatter(BaseFormatter): - """A JSON string formatter. - - To define the callables that compute the JSONable representation of - your objects, define a :meth:`_repr_json_` method or use the :meth:`for_type` - or :meth:`for_type_by_name` methods to register functions that handle - this. - - The return value of this formatter should be a JSONable list or dict. - JSON scalars (None, number, string) are not allowed, only dict or list containers. - """ - format_type = Unicode('application/json') - _return_type = (list, dict) - - print_method = ObjectName('_repr_json_') - - def _check_return(self, r, obj): - """Check that a return value is appropriate - - Return the value if so, None otherwise, warning if invalid. - """ - if r is None: - return - md = None - if isinstance(r, tuple): - # unpack data, metadata tuple for type checking on first element - r, md = r - - assert not isinstance( - r, str - ), "JSON-as-string has been deprecated since IPython < 3" - - if md is not None: - # put the tuple back together - r = (r, md) - return super(JSONFormatter, self)._check_return(r, obj) - - -class JavascriptFormatter(BaseFormatter): - """A Javascript formatter. - - To define the callables that compute the Javascript representation of - your objects, define a :meth:`_repr_javascript_` method or use the - :meth:`for_type` or :meth:`for_type_by_name` methods to register functions - that handle this. - - The return value of this formatter should be valid Javascript code and - should *not* be enclosed in ```<script>``` tags. - """ - format_type = Unicode('application/javascript') - - print_method = ObjectName('_repr_javascript_') - - -class PDFFormatter(BaseFormatter): - """A PDF formatter. - - To define the callables that compute the PDF representation of your - objects, define a :meth:`_repr_pdf_` method or use the :meth:`for_type` - or :meth:`for_type_by_name` methods to register functions that handle - this. - - The return value of this formatter should be raw PDF data, *not* - base64 encoded. - """ - format_type = Unicode('application/pdf') - - print_method = ObjectName('_repr_pdf_') - - _return_type = (bytes, str) - -class IPythonDisplayFormatter(BaseFormatter): - """An escape-hatch Formatter for objects that know how to display themselves. - - To define the callables that compute the representation of your - objects, define a :meth:`_ipython_display_` method or use the :meth:`for_type` - or :meth:`for_type_by_name` methods to register functions that handle - this. Unlike mime-type displays, this method should not return anything, - instead calling any appropriate display methods itself. - - This display formatter has highest priority. - If it fires, no other display formatter will be called. - - Prior to IPython 6.1, `_ipython_display_` was the only way to display custom mime-types - without registering a new Formatter. - - IPython 6.1 introduces `_repr_mimebundle_` for displaying custom mime-types, - so `_ipython_display_` should only be used for objects that require unusual - display patterns, such as multiple display calls. - """ - print_method = ObjectName('_ipython_display_') - _return_type = (type(None), bool) - - @catch_format_error - def __call__(self, obj): - """Compute the format for an object.""" - if self.enabled: - # lookup registered printer - try: - printer = self.lookup(obj) - except KeyError: - pass - else: - printer(obj) - return True - # Finally look for special method names - method = get_real_method(obj, self.print_method) - if method is not None: - method() - return True - - -class MimeBundleFormatter(BaseFormatter): - """A Formatter for arbitrary mime-types. - - Unlike other `_repr_<mimetype>_` methods, - `_repr_mimebundle_` should return mime-bundle data, - either the mime-keyed `data` dictionary or the tuple `(data, metadata)`. - Any mime-type is valid. - - To define the callables that compute the mime-bundle representation of your - objects, define a :meth:`_repr_mimebundle_` method or use the :meth:`for_type` - or :meth:`for_type_by_name` methods to register functions that handle - this. - - .. versionadded:: 6.1 - """ - print_method = ObjectName('_repr_mimebundle_') - _return_type = dict - - def _check_return(self, r, obj): - r = super(MimeBundleFormatter, self)._check_return(r, obj) - # always return (data, metadata): - if r is None: - return {}, {} - if not isinstance(r, tuple): - return r, {} - return r - - @catch_format_error - def __call__(self, obj, include=None, exclude=None): - """Compute the format for an object. - - Identical to parent's method but we pass extra parameters to the method. - - Unlike other _repr_*_ `_repr_mimebundle_` should allow extra kwargs, in - particular `include` and `exclude`. - """ - if self.enabled: - # lookup registered printer - try: - printer = self.lookup(obj) - except KeyError: - pass - else: - return printer(obj) - # Finally look for special method names - method = get_real_method(obj, self.print_method) - - if method is not None: - return method(include=include, exclude=exclude) - return None - else: - return None - - -FormatterABC.register(BaseFormatter) -FormatterABC.register(PlainTextFormatter) -FormatterABC.register(HTMLFormatter) -FormatterABC.register(MarkdownFormatter) -FormatterABC.register(SVGFormatter) -FormatterABC.register(PNGFormatter) -FormatterABC.register(PDFFormatter) -FormatterABC.register(JPEGFormatter) -FormatterABC.register(LatexFormatter) -FormatterABC.register(JSONFormatter) -FormatterABC.register(JavascriptFormatter) -FormatterABC.register(IPythonDisplayFormatter) -FormatterABC.register(MimeBundleFormatter) - - -def format_display_data(obj, include=None, exclude=None): - """Return a format data dict for an object. - - By default all format types will be computed. - - Parameters - ---------- - obj : object - The Python object whose format data will be computed. - - Returns - ------- - format_dict : dict - A dictionary of key/value pairs, one or each format that was - generated for the object. The keys are the format types, which - will usually be MIME type strings and the values and JSON'able - data structure containing the raw data for the representation in - that format. - include : list or tuple, optional - A list of format type strings (MIME types) to include in the - format data dict. If this is set *only* the format types included - in this list will be computed. - exclude : list or tuple, optional - A list of format type string (MIME types) to exclude in the format - data dict. If this is set all format types will be computed, - except for those included in this argument. - """ - from .interactiveshell import InteractiveShell - - return InteractiveShell.instance().display_formatter.format( - obj, - include, - exclude - ) diff --git a/contrib/python/ipython/py3/IPython/core/getipython.py b/contrib/python/ipython/py3/IPython/core/getipython.py deleted file mode 100644 index 5e9b13cf3c..0000000000 --- a/contrib/python/ipython/py3/IPython/core/getipython.py +++ /dev/null @@ -1,24 +0,0 @@ -# encoding: utf-8 -"""Simple function to call to get the current InteractiveShell instance -""" - -#----------------------------------------------------------------------------- -# Copyright (C) 2013 The IPython Development Team -# -# Distributed under the terms of the BSD License. The full license is in -# the file COPYING, distributed as part of this software. -#----------------------------------------------------------------------------- - -#----------------------------------------------------------------------------- -# Classes and functions -#----------------------------------------------------------------------------- - - -def get_ipython(): - """Get the global InteractiveShell instance. - - Returns None if no InteractiveShell instance is registered. - """ - from IPython.core.interactiveshell import InteractiveShell - if InteractiveShell.initialized(): - return InteractiveShell.instance() diff --git a/contrib/python/ipython/py3/IPython/core/history.py b/contrib/python/ipython/py3/IPython/core/history.py deleted file mode 100644 index 9b0b2cbd04..0000000000 --- a/contrib/python/ipython/py3/IPython/core/history.py +++ /dev/null @@ -1,938 +0,0 @@ -""" History related magics and functionality """ - -# Copyright (c) IPython Development Team. -# Distributed under the terms of the Modified BSD License. - - -import atexit -import datetime -from pathlib import Path -import re -import sqlite3 -import threading - -from traitlets.config.configurable import LoggingConfigurable -from decorator import decorator -from IPython.utils.decorators import undoc -from IPython.paths import locate_profile -from traitlets import ( - Any, - Bool, - Dict, - Instance, - Integer, - List, - Unicode, - Union, - TraitError, - default, - observe, -) - -#----------------------------------------------------------------------------- -# Classes and functions -#----------------------------------------------------------------------------- - -@undoc -class DummyDB(object): - """Dummy DB that will act as a black hole for history. - - Only used in the absence of sqlite""" - def execute(*args, **kwargs): - return [] - - def commit(self, *args, **kwargs): - pass - - def __enter__(self, *args, **kwargs): - pass - - def __exit__(self, *args, **kwargs): - pass - - -@decorator -def only_when_enabled(f, self, *a, **kw): - """Decorator: return an empty list in the absence of sqlite.""" - if not self.enabled: - return [] - else: - return f(self, *a, **kw) - - -# 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. - """ - try: - return f(self, *a, **kw) - except (sqlite3.DatabaseError, sqlite3.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 self.hist_file.is_file(): - # move the file out of the way - base = str(self.hist_file.parent / self.hist_file.stem) - ext = self.hist_file.suffix - size = self.hist_file.stat().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 Path(newpath).exists(): - 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 - self.hist_file.rename(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 - raise - - -class HistoryAccessorBase(LoggingConfigurable): - """An abstract class for History Accessors """ - - def get_tail(self, n=10, raw=True, output=False, include_latest=False): - raise NotImplementedError - - def search(self, pattern="*", raw=True, search_raw=True, - output=False, n=None, unique=False): - raise NotImplementedError - - def get_range(self, session, start=1, stop=None, raw=True,output=False): - raise NotImplementedError - - def get_range_by_str(self, rangestr, raw=True, output=False): - raise NotImplementedError - - -class HistoryAccessor(HistoryAccessorBase): - """Access the history database without adding to it. - - 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 - - # String holding the path to the history file - hist_file = Union( - [Instance(Path), Unicode()], - help="""Path to file to use for SQLite history database. - - By default, IPython will put the history database in the IPython - profile directory. If you would rather share one history among - profiles, you can set this value in each, so that they are consistent. - - Due to an issue with fcntl, SQLite is known to misbehave on some NFS - mounts. If you see IPython hanging, try setting this to something on a - 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. - - """, - ).tag(config=True) - - enabled = Bool(True, - help="""enable the SQLite history - - set enabled=False to disable the SQLite history, - in which case there will be no stored history, no SQLite connection, - and no background saving thread. This may be necessary in some - threaded environments where IPython is embedded. - """, - ).tag(config=True) - - connection_options = Dict( - help="""Options for configuring the SQLite connection - - These options are passed as keyword args to sqlite3.connect - when establishing database connections. - """ - ).tag(config=True) - - # The SQLite database - db = Any() - @observe('db') - def _db_changed(self, change): - """validate the db, since it can be an Instance of two different types""" - new = change['new'] - connection_types = (DummyDB, sqlite3.Connection) - if not isinstance(new, connection_types): - msg = "%s.db must be sqlite3 Connection or DummyDB, not %r" % \ - (self.__class__.__name__, new) - raise TraitError(msg) - - def __init__(self, profile="default", hist_file="", **traits): - """Create a new history accessor. - - Parameters - ---------- - profile : str - The name of the profile from which to open history. - hist_file : str - Path to an SQLite history database stored by IPython. If specified, - hist_file overrides profile. - config : :class:`~traitlets.config.loader.Config` - Config object. hist_file can also be set through this. - """ - # We need a pointer back to the shell for various tasks. - super(HistoryAccessor, self).__init__(**traits) - # defer setting hist_file from kwarg until after init, - # otherwise the default kwarg value would clobber any value - # set by config - if hist_file: - self.hist_file = hist_file - - try: - self.hist_file - except TraitError: - # No one has set the hist_file, yet. - self.hist_file = self._get_hist_file_name(profile) - - self.init_db() - - def _get_hist_file_name(self, profile='default'): - """Find the history file for the given profile name. - - This is overridden by the HistoryManager subclass, to use the shell's - active profile. - - Parameters - ---------- - profile : str - The name of a profile which has a history file. - """ - return Path(locate_profile(profile)) / "history.sqlite" - - @catch_corrupt_db - def init_db(self): - """Connect to the database, and create tables if necessary.""" - if not self.enabled: - self.db = DummyDB() - return - - # use detect_types so that timestamps return datetime objects - kwargs = dict(detect_types=sqlite3.PARSE_DECLTYPES|sqlite3.PARSE_COLNAMES) - kwargs.update(self.connection_options) - self.db = sqlite3.connect(str(self.hist_file), **kwargs) - with self.db: - self.db.execute( - """CREATE TABLE IF NOT EXISTS sessions (session integer - primary key autoincrement, start timestamp, - end timestamp, num_cmds integer, remark text)""" - ) - self.db.execute( - """CREATE TABLE IF NOT EXISTS history - (session integer, line integer, source text, source_raw text, - PRIMARY KEY (session, line))""" - ) - # Output history is optional, but ensure the table's there so it can be - # enabled later. - self.db.execute( - """CREATE TABLE IF NOT EXISTS output_history - (session integer, line integer, output text, - PRIMARY KEY (session, line))""" - ) - # success! reset corrupt db count - self._corrupt_db_counter = 0 - - def writeout_cache(self): - """Overridden by HistoryManager to dump the cache before certain - database lookups.""" - pass - - ## ------------------------------- - ## Methods for retrieving history: - ## ------------------------------- - def _run_sql(self, sql, params, raw=True, output=False, latest=False): - """Prepares and runs an SQL query for the history database. - - Parameters - ---------- - sql : str - Any filtering expressions to go after SELECT ... FROM ... - params : tuple - Parameters passed to the SQL query (to replace "?") - raw, output : bool - See :meth:`get_range` - latest : bool - Select rows with max (session, line) - - Returns - ------- - Tuples as :meth:`get_range` - """ - toget = 'source_raw' if raw else 'source' - sqlfrom = "history" - if output: - sqlfrom = "history LEFT JOIN output_history USING (session, line)" - toget = "history.%s, output_history.output" % toget - if latest: - toget += ", MAX(session * 128 * 1024 + line)" - this_querry = "SELECT session, line, %s FROM %s " % (toget, sqlfrom) + sql - cur = self.db.execute(this_querry, params) - if latest: - cur = (row[:-1] for row in cur) - if output: # Regroup into 3-tuples, and parse JSON - return ((ses, lin, (inp, out)) for ses, lin, inp, out in cur) - return cur - - @only_when_enabled - @catch_corrupt_db - def get_session_info(self, session): - """Get info about a session. - - Parameters - ---------- - session : int - Session number to retrieve. - - Returns - ------- - session_id : int - Session ID number - start : datetime - Timestamp for the start of the session. - end : datetime - Timestamp for the end of the session, or None if IPython crashed. - num_cmds : int - Number of commands run, or None if IPython crashed. - remark : unicode - A manually set description. - """ - query = "SELECT * from sessions where session == ?" - return self.db.execute(query, (session,)).fetchone() - - @catch_corrupt_db - def get_last_session_id(self): - """Get the last session ID currently in the database. - - Within IPython, this should be the same as the value stored in - :attr:`HistoryManager.session_number`. - """ - for record in self.get_tail(n=1, include_latest=True): - return record[0] - - @catch_corrupt_db - def get_tail(self, n=10, raw=True, output=False, include_latest=False): - """Get the last n lines from the history database. - - Most recent entry last. - - Completion will be reordered so that that the last ones are when - possible from current session. - - Parameters - ---------- - n : int - The number of lines to get - raw, output : bool - See :meth:`get_range` - include_latest : bool - If False (default), n+1 lines are fetched, and the latest one - is discarded. This is intended to be used where the function - is called by a user command, which it should not return. - - Returns - ------- - Tuples as :meth:`get_range` - """ - self.writeout_cache() - if not include_latest: - n += 1 - # cursor/line/entry - this_cur = list( - self._run_sql( - "WHERE session == ? ORDER BY line DESC LIMIT ? ", - (self.session_number, n), - raw=raw, - output=output, - ) - ) - other_cur = list( - self._run_sql( - "WHERE session != ? ORDER BY session DESC, line DESC LIMIT ?", - (self.session_number, n), - raw=raw, - output=output, - ) - ) - - everything = this_cur + other_cur - - everything = everything[:n] - - if not include_latest: - return list(everything)[:0:-1] - return list(everything)[::-1] - - @catch_corrupt_db - def search(self, pattern="*", raw=True, search_raw=True, - output=False, n=None, unique=False): - """Search the database using unix glob-style matching (wildcards - * and ?). - - Parameters - ---------- - pattern : str - The wildcarded pattern to match when searching - search_raw : bool - If True, search the raw input, otherwise, the parsed input - raw, output : bool - See :meth:`get_range` - n : None or int - If an integer is given, it defines the limit of - returned entries. - unique : bool - When it is true, return only unique entries. - - Returns - ------- - Tuples as :meth:`get_range` - """ - tosearch = "source_raw" if search_raw else "source" - if output: - tosearch = "history." + tosearch - self.writeout_cache() - sqlform = "WHERE %s GLOB ?" % tosearch - params = (pattern,) - if unique: - sqlform += ' GROUP BY {0}'.format(tosearch) - if n is not None: - sqlform += " ORDER BY session DESC, line DESC LIMIT ?" - params += (n,) - elif unique: - sqlform += " ORDER BY session, line" - cur = self._run_sql(sqlform, params, raw=raw, output=output, latest=unique) - if n is not None: - return reversed(list(cur)) - return cur - - @catch_corrupt_db - def get_range(self, session, start=1, stop=None, raw=True,output=False): - """Retrieve input by session. - - Parameters - ---------- - session : int - Session number to retrieve. - start : int - First line to retrieve. - stop : int - End of line range (excluded from output itself). If None, retrieve - to the end of the session. - raw : bool - If True, return untranslated input - output : bool - If True, attempt to include output. This will be 'real' Python - objects for the current session, or text reprs from previous - sessions if db_log_output was enabled at the time. Where no output - is found, None is used. - - Returns - ------- - entries - An iterator over the desired lines. Each line is a 3-tuple, either - (session, line, input) if output is False, or - (session, line, (input, output)) if output is True. - """ - if stop: - lineclause = "line >= ? AND line < ?" - params = (session, start, stop) - else: - lineclause = "line>=?" - params = (session, start) - - return self._run_sql("WHERE session==? AND %s" % lineclause, - params, raw=raw, output=output) - - def get_range_by_str(self, rangestr, raw=True, output=False): - """Get lines of history from a string of ranges, as used by magic - commands %hist, %save, %macro, etc. - - Parameters - ---------- - rangestr : str - A string specifying ranges, e.g. "5 ~2/1-4". If empty string is used, - this will return everything from current session's history. - - See the documentation of :func:`%history` for the full details. - - raw, output : bool - As :meth:`get_range` - - Returns - ------- - Tuples as :meth:`get_range` - """ - for sess, s, e in extract_hist_ranges(rangestr): - for line in self.get_range(sess, s, e, raw=raw, output=output): - yield line - - -class HistoryManager(HistoryAccessor): - """A class to organize all history-related functionality in one place. - """ - # Public interface - - # An instance of the IPython shell we are attached to - shell = Instance('IPython.core.interactiveshell.InteractiveShellABC', - allow_none=True) - # Lists to hold processed and raw history. These start with a blank entry - # so that we can index them starting from 1 - input_hist_parsed = List([""]) - input_hist_raw = List([""]) - # A list of directories visited during session - dir_hist = List() - @default('dir_hist') - def _dir_hist_default(self): - try: - return [Path.cwd()] - except OSError: - return [] - - # A dict of output history, keyed with ints from the shell's - # execution count. - output_hist = Dict() - # The text/plain repr of outputs. - output_hist_reprs = Dict() - - # The number of the current session in the history database - session_number = Integer() - - db_log_output = Bool(False, - help="Should the history database include output? (default: no)" - ).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) - # The input and output caches - db_input_cache = List() - db_output_cache = List() - - # History saving in separate thread - save_thread = Instance('IPython.core.history.HistorySavingThread', - allow_none=True) - save_flag = Instance(threading.Event, allow_none=True) - - # Private interface - # Variables used to store the three last inputs from the user. On each new - # history update, we populate the user's namespace with these, shifted as - # necessary. - _i00 = Unicode(u'') - _i = Unicode(u'') - _ii = Unicode(u'') - _iii = Unicode(u'') - - # A regex matching all forms of the exit command, so that we don't store - # them in the history (it's annoying to rewind the first entry and land on - # an exit call). - _exit_re = re.compile(r"(exit|quit)(\s*\(.*\))?$") - - def __init__(self, shell=None, config=None, **traits): - """Create a new history manager associated with a shell instance. - """ - # We need a pointer back to the shell for various tasks. - super(HistoryManager, self).__init__(shell=shell, config=config, - **traits) - self.save_flag = threading.Event() - self.db_input_cache_lock = threading.Lock() - self.db_output_cache_lock = threading.Lock() - - try: - self.new_session() - except sqlite3.OperationalError: - self.log.error("Failed to create history session in %s. History will not be saved.", - self.hist_file, exc_info=True) - self.hist_file = ':memory:' - - if self.enabled and self.hist_file != ':memory:': - self.save_thread = HistorySavingThread(self) - self.save_thread.start() - - def _get_hist_file_name(self, profile=None): - """Get default history file name based on the Shell's profile. - - The profile parameter is ignored, but must exist for compatibility with - the parent class.""" - profile_dir = self.shell.profile_dir.location - return Path(profile_dir) / "history.sqlite" - - @only_when_enabled - def new_session(self, conn=None): - """Get a new session number.""" - if conn is None: - conn = self.db - - with conn: - cur = conn.execute("""INSERT INTO sessions VALUES (NULL, ?, NULL, - NULL, "") """, (datetime.datetime.now(),)) - self.session_number = cur.lastrowid - - def end_session(self): - """Close the database session, filling in the end time and line count.""" - self.writeout_cache() - with self.db: - self.db.execute("""UPDATE sessions SET end=?, num_cmds=? WHERE - session==?""", (datetime.datetime.now(), - len(self.input_hist_parsed)-1, self.session_number)) - self.session_number = 0 - - def name_session(self, name): - """Give the current session a name in the history database.""" - with self.db: - self.db.execute("UPDATE sessions SET remark=? WHERE session==?", - (name, self.session_number)) - - def reset(self, new_session=True): - """Clear the session history, releasing all object references, and - optionally open a new session.""" - self.output_hist.clear() - # The directory history can't be completely empty - self.dir_hist[:] = [Path.cwd()] - - if new_session: - if self.session_number: - self.end_session() - self.input_hist_parsed[:] = [""] - self.input_hist_raw[:] = [""] - self.new_session() - - # ------------------------------ - # Methods for retrieving history - # ------------------------------ - def get_session_info(self, session=0): - """Get info about a session. - - Parameters - ---------- - session : int - Session number to retrieve. The current session is 0, and negative - numbers count back from current session, so -1 is the previous session. - - Returns - ------- - session_id : int - Session ID number - start : datetime - Timestamp for the start of the session. - end : datetime - Timestamp for the end of the session, or None if IPython crashed. - num_cmds : int - Number of commands run, or None if IPython crashed. - remark : unicode - A manually set description. - """ - if session <= 0: - session += self.session_number - - return super(HistoryManager, self).get_session_info(session=session) - - def _get_range_session(self, start=1, stop=None, raw=True, output=False): - """Get input and output history from the current session. Called by - get_range, and takes similar parameters.""" - input_hist = self.input_hist_raw if raw else self.input_hist_parsed - - n = len(input_hist) - if start < 0: - start += n - if not stop or (stop > n): - stop = n - elif stop < 0: - stop += n - - for i in range(start, stop): - if output: - line = (input_hist[i], self.output_hist_reprs.get(i)) - else: - line = input_hist[i] - yield (0, i, line) - - def get_range(self, session=0, start=1, stop=None, raw=True,output=False): - """Retrieve input by session. - - Parameters - ---------- - session : int - Session number to retrieve. The current session is 0, and negative - numbers count back from current session, so -1 is previous session. - start : int - First line to retrieve. - stop : int - End of line range (excluded from output itself). If None, retrieve - to the end of the session. - raw : bool - If True, return untranslated input - output : bool - If True, attempt to include output. This will be 'real' Python - objects for the current session, or text reprs from previous - sessions if db_log_output was enabled at the time. Where no output - is found, None is used. - - Returns - ------- - entries - An iterator over the desired lines. Each line is a 3-tuple, either - (session, line, input) if output is False, or - (session, line, (input, output)) if output is True. - """ - if session <= 0: - session += self.session_number - if session==self.session_number: # Current session - return self._get_range_session(start, stop, raw, output) - return super(HistoryManager, self).get_range(session, start, stop, raw, - output) - - ## ---------------------------- - ## Methods for storing history: - ## ---------------------------- - def store_inputs(self, line_num, source, source_raw=None): - """Store source and raw input in history and create input cache - variables ``_i*``. - - Parameters - ---------- - line_num : int - The prompt number of this input. - source : str - Python input. - source_raw : str, optional - If given, this is the raw input without any IPython transformations - applied to it. If not given, ``source`` is used. - """ - if source_raw is None: - source_raw = source - source = source.rstrip('\n') - source_raw = source_raw.rstrip('\n') - - # do not store exit/quit commands - if self._exit_re.match(source_raw.strip()): - return - - self.input_hist_parsed.append(source) - self.input_hist_raw.append(source_raw) - - with self.db_input_cache_lock: - self.db_input_cache.append((line_num, source, source_raw)) - # Trigger to flush cache and write to DB. - if len(self.db_input_cache) >= self.db_cache_size: - self.save_flag.set() - - # update the auto _i variables - self._iii = self._ii - self._ii = self._i - self._i = self._i00 - self._i00 = source_raw - - # hackish access to user namespace to create _i1,_i2... dynamically - new_i = '_i%s' % line_num - to_main = {'_i': self._i, - '_ii': self._ii, - '_iii': self._iii, - new_i : self._i00 } - - if self.shell is not None: - self.shell.push(to_main, interactive=False) - - def store_output(self, line_num): - """If database output logging is enabled, this saves all the - outputs from the indicated prompt number to the database. It's - called by run_cell after code has been executed. - - Parameters - ---------- - line_num : int - The line number from which to save outputs - """ - if (not self.db_log_output) or (line_num not in self.output_hist_reprs): - return - output = self.output_hist_reprs[line_num] - - with self.db_output_cache_lock: - self.db_output_cache.append((line_num, output)) - if self.db_cache_size <= 1: - self.save_flag.set() - - def _writeout_input_cache(self, conn): - with conn: - for line in self.db_input_cache: - conn.execute("INSERT INTO history VALUES (?, ?, ?, ?)", - (self.session_number,)+line) - - def _writeout_output_cache(self, conn): - with conn: - for line in self.db_output_cache: - conn.execute("INSERT INTO output_history VALUES (?, ?, ?)", - (self.session_number,)+line) - - @only_when_enabled - def writeout_cache(self, conn=None): - """Write any entries in the cache to the database.""" - if conn is None: - conn = self.db - - with self.db_input_cache_lock: - try: - self._writeout_input_cache(conn) - except sqlite3.IntegrityError: - self.new_session(conn) - print("ERROR! Session/line number was not unique in", - "database. History logging moved to new session", - self.session_number) - try: - # Try writing to the new session. If this fails, don't - # recurse - self._writeout_input_cache(conn) - except sqlite3.IntegrityError: - pass - finally: - self.db_input_cache = [] - - with self.db_output_cache_lock: - try: - self._writeout_output_cache(conn) - except sqlite3.IntegrityError: - print("!! Session/line number for output was not unique", - "in database. Output will not be stored.") - finally: - self.db_output_cache = [] - - -class HistorySavingThread(threading.Thread): - """This thread takes care of writing history to the database, so that - the UI isn't held up while that happens. - - It waits for the HistoryManager's save_flag to be set, then writes out - the history cache. The main thread is responsible for setting the flag when - the cache size reaches a defined threshold.""" - daemon = True - stop_now = False - enabled = True - def __init__(self, history_manager): - super(HistorySavingThread, self).__init__(name="IPythonHistorySavingThread") - self.history_manager = history_manager - self.enabled = history_manager.enabled - atexit.register(self.stop) - - @only_when_enabled - def run(self): - # We need a separate db connection per thread: - try: - self.db = sqlite3.connect( - str(self.history_manager.hist_file), - **self.history_manager.connection_options, - ) - while True: - self.history_manager.save_flag.wait() - if self.stop_now: - self.db.close() - return - self.history_manager.save_flag.clear() - self.history_manager.writeout_cache(self.db) - except Exception as e: - print(("The history saving thread hit an unexpected error (%s)." - "History will not be written to the database.") % repr(e)) - - def stop(self): - """This can be called from the main thread to safely stop this thread. - - Note that it does not attempt to write out remaining history before - exiting. That should be done by calling the HistoryManager's - end_session method.""" - self.stop_now = True - self.history_manager.save_flag.set() - self.join() - - -# To match, e.g. ~5/8-~2/3 -range_re = re.compile(r""" -((?P<startsess>~?\d+)/)? -(?P<start>\d+)? -((?P<sep>[\-:]) - ((?P<endsess>~?\d+)/)? - (?P<end>\d+))? -$""", re.VERBOSE) - - -def extract_hist_ranges(ranges_str): - """Turn a string of history ranges into 3-tuples of (session, start, stop). - - Empty string results in a `[(0, 1, None)]`, i.e. "everything from current - session". - - Examples - -------- - >>> list(extract_hist_ranges("~8/5-~7/4 2")) - [(-8, 5, None), (-7, 1, 5), (0, 2, 3)] - """ - if ranges_str == "": - yield (0, 1, None) # Everything from current session - return - - for range_str in ranges_str.split(): - rmatch = range_re.match(range_str) - if not rmatch: - continue - start = rmatch.group("start") - if start: - start = int(start) - end = rmatch.group("end") - # If no end specified, get (a, a + 1) - end = int(end) if end else start + 1 - else: # start not specified - if not rmatch.group('startsess'): # no startsess - continue - start = 1 - end = None # provide the entire session hist - - if rmatch.group("sep") == "-": # 1-3 == 1:4 --> [1, 2, 3] - end += 1 - startsess = rmatch.group("startsess") or "0" - endsess = rmatch.group("endsess") or startsess - startsess = int(startsess.replace("~","-")) - endsess = int(endsess.replace("~","-")) - assert endsess >= startsess, "start session must be earlier than end session" - - if endsess == startsess: - yield (startsess, start, end) - continue - # Multiple sessions in one range: - yield (startsess, start, None) - for sess in range(startsess+1, endsess): - yield (sess, 1, None) - yield (endsess, 1, end) - - -def _format_lineno(session, line): - """Helper function to format line numbers properly.""" - if session == 0: - return str(line) - return "%s#%s" % (session, line) diff --git a/contrib/python/ipython/py3/IPython/core/historyapp.py b/contrib/python/ipython/py3/IPython/core/historyapp.py deleted file mode 100644 index 01a55343f8..0000000000 --- a/contrib/python/ipython/py3/IPython/core/historyapp.py +++ /dev/null @@ -1,161 +0,0 @@ -# encoding: utf-8 -""" -An application for managing IPython history. - -To be invoked as the `ipython history` subcommand. -""" - -import sqlite3 -from pathlib import Path - -from traitlets.config.application import Application -from .application import BaseIPythonApplication -from traitlets import Bool, Int, Dict -from ..utils.io import ask_yes_no - -trim_hist_help = """Trim the IPython history database to the last 1000 entries. - -This actually copies the last 1000 entries to a new database, and then replaces -the old file with the new. Use the `--keep=` argument to specify a number -other than 1000. -""" - -clear_hist_help = """Clear the IPython history database, deleting all entries. - -Because this is a destructive operation, IPython will prompt the user if they -really want to do this. Passing a `-f` flag will force clearing without a -prompt. - -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) - - 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 - ) - )) - - aliases=Dict(dict( - keep = 'HistoryTrim.keep' - )) - - def start(self): - profile_dir = Path(self.profile_dir.location) - hist_file = profile_dir / "history.sqlite" - con = sqlite3.connect(hist_file) - - # Grab the recent history from the current database. - inputs = list(con.execute('SELECT session, line, source, source_raw FROM ' - 'history ORDER BY session DESC, line DESC LIMIT ?', (self.keep+1,))) - if len(inputs) <= self.keep: - print("There are already at most %d entries in the history database." % self.keep) - print("Not doing anything. Use --keep= argument to keep fewer entries") - return - - print("Trimming history to the most recent %d entries." % self.keep) - - inputs.pop() # Remove the extra element we got to check the length. - inputs.reverse() - if inputs: - first_session = inputs[0][0] - outputs = list(con.execute('SELECT session, line, output FROM ' - 'output_history WHERE session >= ?', (first_session,))) - sessions = list(con.execute('SELECT session, start, end, num_cmds, remark FROM ' - 'sessions WHERE session >= ?', (first_session,))) - con.close() - - # Create the new history database. - new_hist_file = profile_dir / "history.sqlite.new" - i = 0 - while new_hist_file.exists(): - # Make sure we don't interfere with an existing file. - i += 1 - new_hist_file = profile_dir / ("history.sqlite.new" + str(i)) - new_db = sqlite3.connect(new_hist_file) - new_db.execute("""CREATE TABLE IF NOT EXISTS sessions (session integer - primary key autoincrement, start timestamp, - end timestamp, num_cmds integer, remark text)""") - new_db.execute("""CREATE TABLE IF NOT EXISTS history - (session integer, line integer, source text, source_raw text, - PRIMARY KEY (session, line))""") - new_db.execute("""CREATE TABLE IF NOT EXISTS output_history - (session integer, line integer, output text, - PRIMARY KEY (session, line))""") - new_db.commit() - - - if inputs: - with new_db: - # Add the recent history into the new database. - new_db.executemany('insert into sessions values (?,?,?,?,?)', sessions) - new_db.executemany('insert into history values (?,?,?,?)', inputs) - new_db.executemany('insert into output_history values (?,?,?)', outputs) - new_db.close() - - if self.backup: - i = 1 - backup_hist_file = profile_dir / ("history.sqlite.old.%d" % i) - while backup_hist_file.exists(): - i += 1 - backup_hist_file = profile_dir / ("history.sqlite.old.%d" % i) - hist_file.rename(backup_hist_file) - print("Backed up longer history file to", backup_hist_file) - else: - hist_file.unlink() - - new_hist_file.rename(hist_file) - -class HistoryClear(HistoryTrim): - description = clear_hist_help - 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) - - flags = Dict(dict( - force = ({'HistoryClear' : {'force' : True}}, - force.help), - f = ({'HistoryTrim' : {'force' : True}}, - force.help - ) - )) - aliases = Dict() - - def start(self): - if self.force or ask_yes_no("Really delete all ipython history? ", - default="no", interrupt="no"): - HistoryTrim.start(self) - -class HistoryApp(Application): - name = u'ipython-history' - description = "Manage the IPython history database." - - subcommands = Dict(dict( - trim = (HistoryTrim, HistoryTrim.description.splitlines()[0]), - clear = (HistoryClear, HistoryClear.description.splitlines()[0]), - )) - - def start(self): - if self.subapp is None: - print("No subcommand specified. Must specify one of: %s" % \ - (self.subcommands.keys())) - print() - self.print_description() - self.print_subcommands() - self.exit(1) - else: - return self.subapp.start() diff --git a/contrib/python/ipython/py3/IPython/core/hooks.py b/contrib/python/ipython/py3/IPython/core/hooks.py deleted file mode 100644 index 09b08d942e..0000000000 --- a/contrib/python/ipython/py3/IPython/core/hooks.py +++ /dev/null @@ -1,171 +0,0 @@ -"""Hooks for IPython. - -In Python, it is possible to overwrite any method of any object if you really -want to. But IPython exposes a few 'hooks', methods which are *designed* to -be overwritten by users for customization purposes. This module defines the -default versions of all such hooks, which get used by IPython if not -overridden by the user. - -Hooks are simple functions, but they should be declared with ``self`` as their -first argument, because when activated they are registered into IPython as -instance methods. The self argument will be the IPython running instance -itself, so hooks have full access to the entire IPython object. - -If you wish to define a new hook and activate it, you can make an :doc:`extension -</config/extensions/index>` or a :ref:`startup script <startup_files>`. For -example, you could use a startup file like this:: - - import os - - def calljed(self,filename, linenum): - "My editor hook calls the jed editor directly." - print "Calling my own editor, jed ..." - if os.system('jed +%d %s' % (linenum,filename)) != 0: - raise TryNext() - - def load_ipython_extension(ip): - ip.set_hook('editor', calljed) - -""" - -#***************************************************************************** -# Copyright (C) 2005 Fernando Perez. <fperez@colorado.edu> -# -# Distributed under the terms of the BSD License. The full license is in -# the file COPYING, distributed as part of this software. -#***************************************************************************** - -import os -import subprocess -import sys - -from .error import TryNext - -# List here all the default hooks. For now it's just the editor functions -# but over time we'll move here all the public API for user-accessible things. - -__all__ = [ - "editor", - "synchronize_with_editor", - "show_in_pager", - "pre_prompt_hook", - "clipboard_get", -] - -deprecated = {'pre_run_code_hook': "a callback for the 'pre_execute' or 'pre_run_cell' event", - 'late_startup_hook': "a callback for the 'shell_initialized' event", - 'shutdown_hook': "the atexit module", - } - -def editor(self, filename, linenum=None, wait=True): - """Open the default editor at the given filename and linenumber. - - This is IPython's default editor hook, you can use it as an example to - write your own modified one. To set your own editor function as the - new editor hook, call ip.set_hook('editor',yourfunc).""" - - # IPython configures a default editor at startup by reading $EDITOR from - # the environment, and falling back on vi (unix) or notepad (win32). - editor = self.editor - - # marker for at which line to open the file (for existing objects) - if linenum is None or editor=='notepad': - linemark = '' - else: - linemark = '+%d' % int(linenum) - - # Enclose in quotes if necessary and legal - if ' ' in editor and os.path.isfile(editor) and editor[0] != '"': - editor = '"%s"' % editor - - # Call the actual editor - proc = subprocess.Popen('%s %s %s' % (editor, linemark, filename), - shell=True) - if wait and proc.wait() != 0: - raise TryNext() - - -def synchronize_with_editor(self, filename, linenum, column): - pass - - -class CommandChainDispatcher: - """ Dispatch calls to a chain of commands until some func can handle it - - Usage: instantiate, execute "add" to add commands (with optional - priority), execute normally via f() calling mechanism. - - """ - def __init__(self,commands=None): - if commands is None: - self.chain = [] - else: - self.chain = commands - - - def __call__(self,*args, **kw): - """ Command chain is called just like normal func. - - This will call all funcs in chain with the same args as were given to - this function, and return the result of first func that didn't raise - TryNext""" - last_exc = TryNext() - for prio,cmd in self.chain: - #print "prio",prio,"cmd",cmd #dbg - try: - return cmd(*args, **kw) - except TryNext as exc: - last_exc = exc - # if no function will accept it, raise TryNext up to the caller - raise last_exc - - def __str__(self): - return str(self.chain) - - def add(self, func, priority=0): - """ Add a func to the cmd chain with given priority """ - self.chain.append((priority, func)) - self.chain.sort(key=lambda x: x[0]) - - def __iter__(self): - """ Return all objects in chain. - - Handy if the objects are not callable. - """ - return iter(self.chain) - - -def show_in_pager(self, data, start, screen_lines): - """ Run a string through pager """ - # raising TryNext here will use the default paging functionality - raise TryNext - - -def pre_prompt_hook(self): - """ Run before displaying the next prompt - - Use this e.g. to display output from asynchronous operations (in order - to not mess up text entry) - """ - - return None - - -def clipboard_get(self): - """ Get text from the clipboard. - """ - from ..lib.clipboard import ( - osx_clipboard_get, tkinter_clipboard_get, - win32_clipboard_get - ) - if sys.platform == 'win32': - chain = [win32_clipboard_get, tkinter_clipboard_get] - elif sys.platform == 'darwin': - chain = [osx_clipboard_get, tkinter_clipboard_get] - else: - chain = [tkinter_clipboard_get] - dispatcher = CommandChainDispatcher() - for func in chain: - dispatcher.add(func) - text = dispatcher() - return text diff --git a/contrib/python/ipython/py3/IPython/core/inputsplitter.py b/contrib/python/ipython/py3/IPython/core/inputsplitter.py deleted file mode 100644 index 01b9c8a5e6..0000000000 --- a/contrib/python/ipython/py3/IPython/core/inputsplitter.py +++ /dev/null @@ -1,772 +0,0 @@ -"""DEPRECATED: Input handling and transformation machinery. - -This module was deprecated in IPython 7.0, in favour of inputtransformer2. - -The first class in this module, :class:`InputSplitter`, is designed to tell when -input from a line-oriented frontend is complete and should be executed, and when -the user should be prompted for another line of code instead. The name 'input -splitter' is largely for historical reasons. - -A companion, :class:`IPythonInputSplitter`, provides the same functionality but -with full support for the extended IPython syntax (magics, system calls, etc). -The code to actually do these transformations is in :mod:`IPython.core.inputtransformer`. -:class:`IPythonInputSplitter` feeds the raw code to the transformers in order -and stores the results. - -For more details, see the class docstrings below. -""" - -from warnings import warn - -warn('IPython.core.inputsplitter is deprecated since IPython 7 in favor of `IPython.core.inputtransformer2`', - DeprecationWarning) - -# Copyright (c) IPython Development Team. -# Distributed under the terms of the Modified BSD License. -import ast -import codeop -import io -import re -import sys -import tokenize -import warnings - -from IPython.core.inputtransformer import (leading_indent, - classic_prompt, - ipy_prompt, - cellmagic, - assemble_logical_lines, - help_end, - escaped_commands, - assign_from_magic, - assign_from_system, - assemble_python_lines, - ) - -# These are available in this module for backwards compatibility. -from IPython.core.inputtransformer import (ESC_SHELL, ESC_SH_CAP, ESC_HELP, - ESC_HELP2, ESC_MAGIC, ESC_MAGIC2, - ESC_QUOTE, ESC_QUOTE2, ESC_PAREN, ESC_SEQUENCES) - -#----------------------------------------------------------------------------- -# Utilities -#----------------------------------------------------------------------------- - -# FIXME: These are general-purpose utilities that later can be moved to the -# general ward. Kept here for now because we're being very strict about test -# coverage with this code, and this lets us ensure that we keep 100% coverage -# while developing. - -# compiled regexps for autoindent management -dedent_re = re.compile('|'.join([ - r'^\s+raise(\s.*)?$', # raise statement (+ space + other stuff, maybe) - r'^\s+raise\([^\)]*\).*$', # wacky raise with immediate open paren - r'^\s+return(\s.*)?$', # normal return (+ space + other stuff, maybe) - r'^\s+return\([^\)]*\).*$', # wacky return with immediate open paren - r'^\s+pass\s*$', # pass (optionally followed by trailing spaces) - r'^\s+break\s*$', # break (optionally followed by trailing spaces) - r'^\s+continue\s*$', # continue (optionally followed by trailing spaces) -])) -ini_spaces_re = re.compile(r'^([ \t\r\f\v]+)') - -# regexp to match pure comment lines so we don't accidentally insert 'if 1:' -# before pure comments -comment_line_re = re.compile(r'^\s*\#') - - -def num_ini_spaces(s): - """Return the number of initial spaces in a string. - - Note that tabs are counted as a single space. For now, we do *not* support - mixing of tabs and spaces in the user's input. - - Parameters - ---------- - s : string - - Returns - ------- - n : int - """ - - ini_spaces = ini_spaces_re.match(s) - if ini_spaces: - return ini_spaces.end() - else: - return 0 - -# Fake token types for partial_tokenize: -INCOMPLETE_STRING = tokenize.N_TOKENS -IN_MULTILINE_STATEMENT = tokenize.N_TOKENS + 1 - -# The 2 classes below have the same API as TokenInfo, but don't try to look up -# a token type name that they won't find. -class IncompleteString: - type = exact_type = INCOMPLETE_STRING - def __init__(self, s, start, end, line): - self.s = s - self.start = start - self.end = end - self.line = line - -class InMultilineStatement: - type = exact_type = IN_MULTILINE_STATEMENT - def __init__(self, pos, line): - self.s = '' - self.start = self.end = pos - self.line = line - -def partial_tokens(s): - """Iterate over tokens from a possibly-incomplete string of code. - - This adds two special token types: INCOMPLETE_STRING and - IN_MULTILINE_STATEMENT. These can only occur as the last token yielded, and - represent the two main ways for code to be incomplete. - """ - readline = io.StringIO(s).readline - token = tokenize.TokenInfo(tokenize.NEWLINE, '', (1, 0), (1, 0), '') - try: - for token in tokenize.generate_tokens(readline): - yield token - except tokenize.TokenError as e: - # catch EOF error - lines = s.splitlines(keepends=True) - end = len(lines), len(lines[-1]) - if 'multi-line string' in e.args[0]: - l, c = start = token.end - s = lines[l-1][c:] + ''.join(lines[l:]) - yield IncompleteString(s, start, end, lines[-1]) - elif 'multi-line statement' in e.args[0]: - yield InMultilineStatement(end, lines[-1]) - else: - raise - -def find_next_indent(code): - """Find the number of spaces for the next line of indentation""" - tokens = list(partial_tokens(code)) - if tokens[-1].type == tokenize.ENDMARKER: - tokens.pop() - if not tokens: - return 0 - while (tokens[-1].type in {tokenize.DEDENT, tokenize.NEWLINE, tokenize.COMMENT}): - tokens.pop() - - if tokens[-1].type == INCOMPLETE_STRING: - # Inside a multiline string - return 0 - - # Find the indents used before - prev_indents = [0] - def _add_indent(n): - if n != prev_indents[-1]: - prev_indents.append(n) - - tokiter = iter(tokens) - for tok in tokiter: - if tok.type in {tokenize.INDENT, tokenize.DEDENT}: - _add_indent(tok.end[1]) - elif (tok.type == tokenize.NL): - try: - _add_indent(next(tokiter).start[1]) - except StopIteration: - break - - last_indent = prev_indents.pop() - - # If we've just opened a multiline statement (e.g. 'a = ['), indent more - if tokens[-1].type == IN_MULTILINE_STATEMENT: - if tokens[-2].exact_type in {tokenize.LPAR, tokenize.LSQB, tokenize.LBRACE}: - return last_indent + 4 - return last_indent - - if tokens[-1].exact_type == tokenize.COLON: - # Line ends with colon - indent - return last_indent + 4 - - if last_indent: - # Examine the last line for dedent cues - statements like return or - # raise which normally end a block of code. - last_line_starts = 0 - for i, tok in enumerate(tokens): - if tok.type == tokenize.NEWLINE: - last_line_starts = i + 1 - - last_line_tokens = tokens[last_line_starts:] - names = [t.string for t in last_line_tokens if t.type == tokenize.NAME] - if names and names[0] in {'raise', 'return', 'pass', 'break', 'continue'}: - # Find the most recent indentation less than the current level - for indent in reversed(prev_indents): - if indent < last_indent: - return indent - - return last_indent - - -def last_blank(src): - """Determine if the input source ends in a blank. - - A blank is either a newline or a line consisting of whitespace. - - Parameters - ---------- - src : string - A single or multiline string. - """ - if not src: return False - ll = src.splitlines()[-1] - return (ll == '') or ll.isspace() - - -last_two_blanks_re = re.compile(r'\n\s*\n\s*$', re.MULTILINE) -last_two_blanks_re2 = re.compile(r'.+\n\s*\n\s+$', re.MULTILINE) - -def last_two_blanks(src): - """Determine if the input source ends in two blanks. - - A blank is either a newline or a line consisting of whitespace. - - Parameters - ---------- - src : string - A single or multiline string. - """ - if not src: return False - # The logic here is tricky: I couldn't get a regexp to work and pass all - # the tests, so I took a different approach: split the source by lines, - # grab the last two and prepend '###\n' as a stand-in for whatever was in - # the body before the last two lines. Then, with that structure, it's - # possible to analyze with two regexps. Not the most elegant solution, but - # it works. If anyone tries to change this logic, make sure to validate - # the whole test suite first! - new_src = '\n'.join(['###\n'] + src.splitlines()[-2:]) - return (bool(last_two_blanks_re.match(new_src)) or - bool(last_two_blanks_re2.match(new_src)) ) - - -def remove_comments(src): - """Remove all comments from input source. - - Note: comments are NOT recognized inside of strings! - - Parameters - ---------- - src : string - A single or multiline input string. - - Returns - ------- - String with all Python comments removed. - """ - - return re.sub('#.*', '', src) - - -def get_input_encoding(): - """Return the default standard input encoding. - - If sys.stdin has no encoding, 'ascii' is returned.""" - # There are strange environments for which sys.stdin.encoding is None. We - # ensure that a valid encoding is returned. - encoding = getattr(sys.stdin, 'encoding', None) - if encoding is None: - encoding = 'ascii' - return encoding - -#----------------------------------------------------------------------------- -# Classes and functions for normal Python syntax handling -#----------------------------------------------------------------------------- - -class InputSplitter(object): - r"""An object that can accumulate lines of Python source before execution. - - This object is designed to be fed python source line-by-line, using - :meth:`push`. It will return on each push whether the currently pushed - code could be executed already. In addition, it provides a method called - :meth:`push_accepts_more` that can be used to query whether more input - can be pushed into a single interactive block. - - This is a simple example of how an interactive terminal-based client can use - this tool:: - - isp = InputSplitter() - while isp.push_accepts_more(): - indent = ' '*isp.indent_spaces - prompt = '>>> ' + indent - line = indent + raw_input(prompt) - isp.push(line) - print 'Input source was:\n', isp.source_reset(), - """ - # A cache for storing the current indentation - # The first value stores the most recently processed source input - # The second value is the number of spaces for the current indentation - # If self.source matches the first value, the second value is a valid - # current indentation. Otherwise, the cache is invalid and the indentation - # must be recalculated. - _indent_spaces_cache = None, None - # String, indicating the default input encoding. It is computed by default - # at initialization time via get_input_encoding(), but it can be reset by a - # client with specific knowledge of the encoding. - encoding = '' - # String where the current full source input is stored, properly encoded. - # Reading this attribute is the normal way of querying the currently pushed - # source code, that has been properly encoded. - source = '' - # Code object corresponding to the current source. It is automatically - # synced to the source, so it can be queried at any time to obtain the code - # object; it will be None if the source doesn't compile to valid Python. - code = None - - # Private attributes - - # List with lines of input accumulated so far - _buffer = None - # Command compiler - _compile = None - # Boolean indicating whether the current block is complete - _is_complete = None - # Boolean indicating whether the current block has an unrecoverable syntax error - _is_invalid = False - - def __init__(self): - """Create a new InputSplitter instance. - """ - self._buffer = [] - self._compile = codeop.CommandCompiler() - self.encoding = get_input_encoding() - - def reset(self): - """Reset the input buffer and associated state.""" - self._buffer[:] = [] - self.source = '' - self.code = None - self._is_complete = False - self._is_invalid = False - - def source_reset(self): - """Return the input source and perform a full reset. - """ - out = self.source - self.reset() - return out - - def check_complete(self, source): - """Return whether a block of code is ready to execute, or should be continued - - This is a non-stateful API, and will reset the state of this InputSplitter. - - Parameters - ---------- - source : string - Python input code, which can be multiline. - - Returns - ------- - status : str - One of 'complete', 'incomplete', or 'invalid' if source is not a - prefix of valid code. - indent_spaces : int or None - The number of spaces by which to indent the next line of code. If - status is not 'incomplete', this is None. - """ - self.reset() - try: - self.push(source) - except SyntaxError: - # Transformers in IPythonInputSplitter can raise SyntaxError, - # which push() will not catch. - return 'invalid', None - else: - if self._is_invalid: - return 'invalid', None - elif self.push_accepts_more(): - return 'incomplete', self.get_indent_spaces() - else: - return 'complete', None - finally: - self.reset() - - def push(self, lines:str) -> bool: - """Push one or more lines of input. - - This stores the given lines and returns a status code indicating - whether the code forms a complete Python block or not. - - Any exceptions generated in compilation are swallowed, but if an - exception was produced, the method returns True. - - Parameters - ---------- - lines : string - One or more lines of Python input. - - Returns - ------- - is_complete : boolean - True if the current input source (the result of the current input - plus prior inputs) forms a complete Python execution block. Note that - this value is also stored as a private attribute (``_is_complete``), so it - can be queried at any time. - """ - assert isinstance(lines, str) - self._store(lines) - source = self.source - - # Before calling _compile(), reset the code object to None so that if an - # exception is raised in compilation, we don't mislead by having - # inconsistent code/source attributes. - self.code, self._is_complete = None, None - self._is_invalid = False - - # Honor termination lines properly - if source.endswith('\\\n'): - return False - - try: - with warnings.catch_warnings(): - warnings.simplefilter('error', SyntaxWarning) - self.code = self._compile(source, symbol="exec") - # Invalid syntax can produce any of a number of different errors from - # inside the compiler, so we have to catch them all. Syntax errors - # immediately produce a 'ready' block, so the invalid Python can be - # sent to the kernel for evaluation with possible ipython - # special-syntax conversion. - except (SyntaxError, OverflowError, ValueError, TypeError, - MemoryError, SyntaxWarning): - self._is_complete = True - self._is_invalid = True - else: - # Compilation didn't produce any exceptions (though it may not have - # given a complete code object) - self._is_complete = self.code is not None - - return self._is_complete - - def push_accepts_more(self): - """Return whether a block of interactive input can accept more input. - - This method is meant to be used by line-oriented frontends, who need to - guess whether a block is complete or not based solely on prior and - current input lines. The InputSplitter considers it has a complete - interactive block and will not accept more input when either: - - * A SyntaxError is raised - - * The code is complete and consists of a single line or a single - non-compound statement - - * The code is complete and has a blank line at the end - - If the current input produces a syntax error, this method immediately - returns False but does *not* raise the syntax error exception, as - typically clients will want to send invalid syntax to an execution - backend which might convert the invalid syntax into valid Python via - one of the dynamic IPython mechanisms. - """ - - # With incomplete input, unconditionally accept more - # A syntax error also sets _is_complete to True - see push() - if not self._is_complete: - #print("Not complete") # debug - return True - - # The user can make any (complete) input execute by leaving a blank line - last_line = self.source.splitlines()[-1] - if (not last_line) or last_line.isspace(): - #print("Blank line") # debug - return False - - # If there's just a single line or AST node, and we're flush left, as is - # the case after a simple statement such as 'a=1', we want to execute it - # straight away. - if self.get_indent_spaces() == 0: - if len(self.source.splitlines()) <= 1: - return False - - try: - code_ast = ast.parse(u''.join(self._buffer)) - except Exception: - #print("Can't parse AST") # debug - return False - else: - if len(code_ast.body) == 1 and \ - not hasattr(code_ast.body[0], 'body'): - #print("Simple statement") # debug - return False - - # General fallback - accept more code - return True - - def get_indent_spaces(self): - sourcefor, n = self._indent_spaces_cache - if sourcefor == self.source: - return n - - # self.source always has a trailing newline - n = find_next_indent(self.source[:-1]) - self._indent_spaces_cache = (self.source, n) - return n - - # Backwards compatibility. I think all code that used .indent_spaces was - # inside IPython, but we can leave this here until IPython 7 in case any - # other modules are using it. -TK, November 2017 - indent_spaces = property(get_indent_spaces) - - def _store(self, lines, buffer=None, store='source'): - """Store one or more lines of input. - - If input lines are not newline-terminated, a newline is automatically - appended.""" - - if buffer is None: - buffer = self._buffer - - if lines.endswith('\n'): - buffer.append(lines) - else: - buffer.append(lines+'\n') - setattr(self, store, self._set_source(buffer)) - - def _set_source(self, buffer): - return u''.join(buffer) - - -class IPythonInputSplitter(InputSplitter): - """An input splitter that recognizes all of IPython's special syntax.""" - - # String with raw, untransformed input. - source_raw = '' - - # Flag to track when a transformer has stored input that it hasn't given - # back yet. - transformer_accumulating = False - - # Flag to track when assemble_python_lines has stored input that it hasn't - # given back yet. - within_python_line = False - - # Private attributes - - # List with lines of raw input accumulated so far. - _buffer_raw = None - - def __init__(self, line_input_checker=True, physical_line_transforms=None, - logical_line_transforms=None, python_line_transforms=None): - super(IPythonInputSplitter, self).__init__() - self._buffer_raw = [] - self._validate = True - - if physical_line_transforms is not None: - self.physical_line_transforms = physical_line_transforms - else: - self.physical_line_transforms = [ - leading_indent(), - classic_prompt(), - ipy_prompt(), - cellmagic(end_on_blank_line=line_input_checker), - ] - - self.assemble_logical_lines = assemble_logical_lines() - if logical_line_transforms is not None: - self.logical_line_transforms = logical_line_transforms - else: - self.logical_line_transforms = [ - help_end(), - escaped_commands(), - assign_from_magic(), - assign_from_system(), - ] - - self.assemble_python_lines = assemble_python_lines() - if python_line_transforms is not None: - self.python_line_transforms = python_line_transforms - else: - # We don't use any of these at present - self.python_line_transforms = [] - - @property - def transforms(self): - "Quick access to all transformers." - return self.physical_line_transforms + \ - [self.assemble_logical_lines] + self.logical_line_transforms + \ - [self.assemble_python_lines] + self.python_line_transforms - - @property - def transforms_in_use(self): - """Transformers, excluding logical line transformers if we're in a - Python line.""" - t = self.physical_line_transforms[:] - if not self.within_python_line: - t += [self.assemble_logical_lines] + self.logical_line_transforms - return t + [self.assemble_python_lines] + self.python_line_transforms - - def reset(self): - """Reset the input buffer and associated state.""" - super(IPythonInputSplitter, self).reset() - self._buffer_raw[:] = [] - self.source_raw = '' - self.transformer_accumulating = False - self.within_python_line = False - - for t in self.transforms: - try: - t.reset() - except SyntaxError: - # Nothing that calls reset() expects to handle transformer - # errors - pass - - def flush_transformers(self): - def _flush(transform, outs): - """yield transformed lines - - always strings, never None - - transform: the current transform - outs: an iterable of previously transformed inputs. - Each may be multiline, which will be passed - one line at a time to transform. - """ - for out in outs: - for line in out.splitlines(): - # push one line at a time - tmp = transform.push(line) - if tmp is not None: - yield tmp - - # reset the transform - tmp = transform.reset() - if tmp is not None: - yield tmp - - out = [] - for t in self.transforms_in_use: - out = _flush(t, out) - - out = list(out) - if out: - self._store('\n'.join(out)) - - def raw_reset(self): - """Return raw input only and perform a full reset. - """ - out = self.source_raw - self.reset() - return out - - def source_reset(self): - try: - self.flush_transformers() - return self.source - finally: - self.reset() - - def push_accepts_more(self): - if self.transformer_accumulating: - return True - else: - return super(IPythonInputSplitter, self).push_accepts_more() - - def transform_cell(self, cell): - """Process and translate a cell of input. - """ - self.reset() - try: - self.push(cell) - self.flush_transformers() - return self.source - finally: - self.reset() - - def push(self, lines:str) -> bool: - """Push one or more lines of IPython input. - - This stores the given lines and returns a status code indicating - whether the code forms a complete Python block or not, after processing - all input lines for special IPython syntax. - - Any exceptions generated in compilation are swallowed, but if an - exception was produced, the method returns True. - - Parameters - ---------- - lines : string - One or more lines of Python input. - - Returns - ------- - is_complete : boolean - True if the current input source (the result of the current input - plus prior inputs) forms a complete Python execution block. Note that - this value is also stored as a private attribute (_is_complete), so it - can be queried at any time. - """ - assert isinstance(lines, str) - # We must ensure all input is pure unicode - # ''.splitlines() --> [], but we need to push the empty line to transformers - lines_list = lines.splitlines() - if not lines_list: - lines_list = [''] - - # Store raw source before applying any transformations to it. Note - # that this must be done *after* the reset() call that would otherwise - # flush the buffer. - self._store(lines, self._buffer_raw, 'source_raw') - - transformed_lines_list = [] - for line in lines_list: - transformed = self._transform_line(line) - if transformed is not None: - transformed_lines_list.append(transformed) - - if transformed_lines_list: - transformed_lines = '\n'.join(transformed_lines_list) - return super(IPythonInputSplitter, self).push(transformed_lines) - else: - # Got nothing back from transformers - they must be waiting for - # more input. - return False - - def _transform_line(self, line): - """Push a line of input code through the various transformers. - - Returns any output from the transformers, or None if a transformer - is accumulating lines. - - Sets self.transformer_accumulating as a side effect. - """ - def _accumulating(dbg): - #print(dbg) - self.transformer_accumulating = True - return None - - for transformer in self.physical_line_transforms: - line = transformer.push(line) - if line is None: - return _accumulating(transformer) - - if not self.within_python_line: - line = self.assemble_logical_lines.push(line) - if line is None: - return _accumulating('acc logical line') - - for transformer in self.logical_line_transforms: - line = transformer.push(line) - if line is None: - return _accumulating(transformer) - - line = self.assemble_python_lines.push(line) - if line is None: - self.within_python_line = True - return _accumulating('acc python line') - else: - self.within_python_line = False - - for transformer in self.python_line_transforms: - line = transformer.push(line) - if line is None: - return _accumulating(transformer) - - #print("transformers clear") #debug - self.transformer_accumulating = False - return line - diff --git a/contrib/python/ipython/py3/IPython/core/inputtransformer.py b/contrib/python/ipython/py3/IPython/core/inputtransformer.py deleted file mode 100644 index 77f69f388f..0000000000 --- a/contrib/python/ipython/py3/IPython/core/inputtransformer.py +++ /dev/null @@ -1,536 +0,0 @@ -"""DEPRECATED: Input transformer classes to support IPython special syntax. - -This module was deprecated in IPython 7.0, in favour of inputtransformer2. - -This includes the machinery to recognise and transform ``%magic`` commands, -``!system`` commands, ``help?`` querying, prompt stripping, and so forth. -""" -import abc -import functools -import re -import tokenize -from tokenize import generate_tokens, untokenize, TokenError -from io import StringIO - -from IPython.core.splitinput import LineInfo - -#----------------------------------------------------------------------------- -# Globals -#----------------------------------------------------------------------------- - -# The escape sequences that define the syntax transformations IPython will -# apply to user input. These can NOT be just changed here: many regular -# expressions and other parts of the code may use their hardcoded values, and -# for all intents and purposes they constitute the 'IPython syntax', so they -# should be considered fixed. - -ESC_SHELL = '!' # Send line to underlying system shell -ESC_SH_CAP = '!!' # Send line to system shell and capture output -ESC_HELP = '?' # Find information about object -ESC_HELP2 = '??' # Find extra-detailed information about object -ESC_MAGIC = '%' # Call magic function -ESC_MAGIC2 = '%%' # Call cell-magic function -ESC_QUOTE = ',' # Split args on whitespace, quote each as string and call -ESC_QUOTE2 = ';' # Quote all args as a single string, call -ESC_PAREN = '/' # Call first argument with rest of line as arguments - -ESC_SEQUENCES = [ESC_SHELL, ESC_SH_CAP, ESC_HELP ,\ - ESC_HELP2, ESC_MAGIC, ESC_MAGIC2,\ - ESC_QUOTE, ESC_QUOTE2, ESC_PAREN ] - - -class InputTransformer(metaclass=abc.ABCMeta): - """Abstract base class for line-based input transformers.""" - - @abc.abstractmethod - def push(self, line): - """Send a line of input to the transformer, returning the transformed - input or None if the transformer is waiting for more input. - - Must be overridden by subclasses. - - Implementations may raise ``SyntaxError`` if the input is invalid. No - other exceptions may be raised. - """ - pass - - @abc.abstractmethod - def reset(self): - """Return, transformed any lines that the transformer has accumulated, - and reset its internal state. - - Must be overridden by subclasses. - """ - pass - - @classmethod - def wrap(cls, func): - """Can be used by subclasses as a decorator, to return a factory that - will allow instantiation with the decorated object. - """ - @functools.wraps(func) - def transformer_factory(**kwargs): - return cls(func, **kwargs) - - return transformer_factory - -class StatelessInputTransformer(InputTransformer): - """Wrapper for a stateless input transformer implemented as a function.""" - def __init__(self, func): - self.func = func - - def __repr__(self): - return "StatelessInputTransformer(func={0!r})".format(self.func) - - def push(self, line): - """Send a line of input to the transformer, returning the - transformed input.""" - return self.func(line) - - def reset(self): - """No-op - exists for compatibility.""" - pass - -class CoroutineInputTransformer(InputTransformer): - """Wrapper for an input transformer implemented as a coroutine.""" - def __init__(self, coro, **kwargs): - # Prime it - self.coro = coro(**kwargs) - next(self.coro) - - def __repr__(self): - return "CoroutineInputTransformer(coro={0!r})".format(self.coro) - - def push(self, line): - """Send a line of input to the transformer, returning the - transformed input or None if the transformer is waiting for more - input. - """ - return self.coro.send(line) - - def reset(self): - """Return, transformed any lines that the transformer has - accumulated, and reset its internal state. - """ - return self.coro.send(None) - -class TokenInputTransformer(InputTransformer): - """Wrapper for a token-based input transformer. - - func should accept a list of tokens (5-tuples, see tokenize docs), and - return an iterable which can be passed to tokenize.untokenize(). - """ - def __init__(self, func): - self.func = func - self.buf = [] - self.reset_tokenizer() - - def reset_tokenizer(self): - it = iter(self.buf) - self.tokenizer = generate_tokens(it.__next__) - - def push(self, line): - self.buf.append(line + '\n') - if all(l.isspace() for l in self.buf): - return self.reset() - - tokens = [] - stop_at_NL = False - try: - for intok in self.tokenizer: - tokens.append(intok) - t = intok[0] - if t == tokenize.NEWLINE or (stop_at_NL and t == tokenize.NL): - # Stop before we try to pull a line we don't have yet - break - elif t == tokenize.ERRORTOKEN: - stop_at_NL = True - except TokenError: - # Multi-line statement - stop and try again with the next line - self.reset_tokenizer() - return None - - return self.output(tokens) - - def output(self, tokens): - self.buf.clear() - self.reset_tokenizer() - return untokenize(self.func(tokens)).rstrip('\n') - - def reset(self): - l = ''.join(self.buf) - self.buf.clear() - self.reset_tokenizer() - if l: - return l.rstrip('\n') - -class assemble_python_lines(TokenInputTransformer): - def __init__(self): - super(assemble_python_lines, self).__init__(None) - - def output(self, tokens): - return self.reset() - -@CoroutineInputTransformer.wrap -def assemble_logical_lines(): - r"""Join lines following explicit line continuations (\)""" - line = '' - while True: - line = (yield line) - if not line or line.isspace(): - continue - - parts = [] - while line is not None: - if line.endswith('\\') and (not has_comment(line)): - parts.append(line[:-1]) - line = (yield None) # Get another line - else: - parts.append(line) - break - - # Output - line = ''.join(parts) - -# Utilities -def _make_help_call(target, esc, lspace): - """Prepares a pinfo(2)/psearch call from a target name and the escape - (i.e. ? or ??)""" - method = 'pinfo2' if esc == '??' \ - else 'psearch' if '*' in target \ - else 'pinfo' - arg = " ".join([method, target]) - #Prepare arguments for get_ipython().run_line_magic(magic_name, magic_args) - t_magic_name, _, t_magic_arg_s = arg.partition(' ') - t_magic_name = t_magic_name.lstrip(ESC_MAGIC) - return "%sget_ipython().run_line_magic(%r, %r)" % ( - lspace, - t_magic_name, - t_magic_arg_s, - ) - - -# These define the transformations for the different escape characters. -def _tr_system(line_info): - "Translate lines escaped with: !" - cmd = line_info.line.lstrip().lstrip(ESC_SHELL) - return '%sget_ipython().system(%r)' % (line_info.pre, cmd) - -def _tr_system2(line_info): - "Translate lines escaped with: !!" - cmd = line_info.line.lstrip()[2:] - return '%sget_ipython().getoutput(%r)' % (line_info.pre, cmd) - -def _tr_help(line_info): - "Translate lines escaped with: ?/??" - # A naked help line should just fire the intro help screen - if not line_info.line[1:]: - return 'get_ipython().show_usage()' - - return _make_help_call(line_info.ifun, line_info.esc, line_info.pre) - -def _tr_magic(line_info): - "Translate lines escaped with: %" - tpl = '%sget_ipython().run_line_magic(%r, %r)' - if line_info.line.startswith(ESC_MAGIC2): - return line_info.line - cmd = ' '.join([line_info.ifun, line_info.the_rest]).strip() - #Prepare arguments for get_ipython().run_line_magic(magic_name, magic_args) - t_magic_name, _, t_magic_arg_s = cmd.partition(' ') - t_magic_name = t_magic_name.lstrip(ESC_MAGIC) - return tpl % (line_info.pre, t_magic_name, t_magic_arg_s) - -def _tr_quote(line_info): - "Translate lines escaped with: ," - return '%s%s("%s")' % (line_info.pre, line_info.ifun, - '", "'.join(line_info.the_rest.split()) ) - -def _tr_quote2(line_info): - "Translate lines escaped with: ;" - return '%s%s("%s")' % (line_info.pre, line_info.ifun, - line_info.the_rest) - -def _tr_paren(line_info): - "Translate lines escaped with: /" - return '%s%s(%s)' % (line_info.pre, line_info.ifun, - ", ".join(line_info.the_rest.split())) - -tr = { ESC_SHELL : _tr_system, - ESC_SH_CAP : _tr_system2, - ESC_HELP : _tr_help, - ESC_HELP2 : _tr_help, - ESC_MAGIC : _tr_magic, - ESC_QUOTE : _tr_quote, - ESC_QUOTE2 : _tr_quote2, - ESC_PAREN : _tr_paren } - -@StatelessInputTransformer.wrap -def escaped_commands(line): - """Transform escaped commands - %magic, !system, ?help + various autocalls. - """ - if not line or line.isspace(): - return line - lineinf = LineInfo(line) - if lineinf.esc not in tr: - return line - - return tr[lineinf.esc](lineinf) - -_initial_space_re = re.compile(r'\s*') - -_help_end_re = re.compile(r"""(%{0,2} - (?!\d)[\w*]+ # Variable name - (\.(?!\d)[\w*]+)* # .etc.etc - ) - (\?\??)$ # ? or ?? - """, - re.VERBOSE) - -# Extra pseudotokens for multiline strings and data structures -_MULTILINE_STRING = object() -_MULTILINE_STRUCTURE = object() - -def _line_tokens(line): - """Helper for has_comment and ends_in_comment_or_string.""" - readline = StringIO(line).readline - toktypes = set() - try: - for t in generate_tokens(readline): - toktypes.add(t[0]) - except TokenError as e: - # There are only two cases where a TokenError is raised. - if 'multi-line string' in e.args[0]: - toktypes.add(_MULTILINE_STRING) - else: - toktypes.add(_MULTILINE_STRUCTURE) - return toktypes - -def has_comment(src): - """Indicate whether an input line has (i.e. ends in, or is) a comment. - - This uses tokenize, so it can distinguish comments from # inside strings. - - Parameters - ---------- - src : string - A single line input string. - - Returns - ------- - comment : bool - True if source has a comment. - """ - return (tokenize.COMMENT in _line_tokens(src)) - -def ends_in_comment_or_string(src): - """Indicates whether or not an input line ends in a comment or within - a multiline string. - - Parameters - ---------- - src : string - A single line input string. - - Returns - ------- - comment : bool - True if source ends in a comment or multiline string. - """ - toktypes = _line_tokens(src) - return (tokenize.COMMENT in toktypes) or (_MULTILINE_STRING in toktypes) - - -@StatelessInputTransformer.wrap -def help_end(line): - """Translate lines with ?/?? at the end""" - m = _help_end_re.search(line) - if m is None or ends_in_comment_or_string(line): - return line - target = m.group(1) - esc = m.group(3) - lspace = _initial_space_re.match(line).group(0) - - return _make_help_call(target, esc, lspace) - - -@CoroutineInputTransformer.wrap -def cellmagic(end_on_blank_line=False): - """Captures & transforms cell magics. - - After a cell magic is started, this stores up any lines it gets until it is - reset (sent None). - """ - tpl = 'get_ipython().run_cell_magic(%r, %r, %r)' - cellmagic_help_re = re.compile(r'%%\w+\?') - line = '' - while True: - line = (yield line) - # consume leading empty lines - while not line: - line = (yield line) - - if not line.startswith(ESC_MAGIC2): - # This isn't a cell magic, idle waiting for reset then start over - while line is not None: - line = (yield line) - continue - - if cellmagic_help_re.match(line): - # This case will be handled by help_end - continue - - first = line - body = [] - line = (yield None) - while (line is not None) and \ - ((line.strip() != '') or not end_on_blank_line): - body.append(line) - line = (yield None) - - # Output - magic_name, _, first = first.partition(' ') - magic_name = magic_name.lstrip(ESC_MAGIC2) - line = tpl % (magic_name, first, u'\n'.join(body)) - - -def _strip_prompts(prompt_re, initial_re=None, turnoff_re=None): - """Remove matching input prompts from a block of input. - - Parameters - ---------- - prompt_re : regular expression - A regular expression matching any input prompt (including continuation) - initial_re : regular expression, optional - A regular expression matching only the initial prompt, but not continuation. - If no initial expression is given, prompt_re will be used everywhere. - Used mainly for plain Python prompts, where the continuation prompt - ``...`` is a valid Python expression in Python 3, so shouldn't be stripped. - - Notes - ----- - If `initial_re` and `prompt_re differ`, - only `initial_re` will be tested against the first line. - If any prompt is found on the first two lines, - prompts will be stripped from the rest of the block. - """ - if initial_re is None: - initial_re = prompt_re - line = '' - while True: - line = (yield line) - - # First line of cell - if line is None: - continue - out, n1 = initial_re.subn('', line, count=1) - if turnoff_re and not n1: - if turnoff_re.match(line): - # We're in e.g. a cell magic; disable this transformer for - # the rest of the cell. - while line is not None: - line = (yield line) - continue - - line = (yield out) - - if line is None: - continue - # check for any prompt on the second line of the cell, - # because people often copy from just after the first prompt, - # so we might not see it in the first line. - out, n2 = prompt_re.subn('', line, count=1) - line = (yield out) - - if n1 or n2: - # Found a prompt in the first two lines - check for it in - # the rest of the cell as well. - while line is not None: - line = (yield prompt_re.sub('', line, count=1)) - - else: - # Prompts not in input - wait for reset - while line is not None: - line = (yield line) - -@CoroutineInputTransformer.wrap -def classic_prompt(): - """Strip the >>>/... prompts of the Python interactive shell.""" - # FIXME: non-capturing version (?:...) usable? - prompt_re = re.compile(r'^(>>>|\.\.\.)( |$)') - initial_re = re.compile(r'^>>>( |$)') - # Any %magic/!system is IPython syntax, so we needn't look for >>> prompts - turnoff_re = re.compile(r'^[%!]') - return _strip_prompts(prompt_re, initial_re, turnoff_re) - -@CoroutineInputTransformer.wrap -def ipy_prompt(): - """Strip IPython's In [1]:/...: prompts.""" - # FIXME: non-capturing version (?:...) usable? - prompt_re = re.compile(r'^(In \[\d+\]: |\s*\.{3,}: ?)') - # Disable prompt stripping inside cell magics - turnoff_re = re.compile(r'^%%') - return _strip_prompts(prompt_re, turnoff_re=turnoff_re) - - -@CoroutineInputTransformer.wrap -def leading_indent(): - """Remove leading indentation. - - If the first line starts with a spaces or tabs, the same whitespace will be - removed from each following line until it is reset. - """ - space_re = re.compile(r'^[ \t]+') - line = '' - while True: - line = (yield line) - - if line is None: - continue - - m = space_re.match(line) - if m: - space = m.group(0) - while line is not None: - if line.startswith(space): - line = line[len(space):] - line = (yield line) - else: - # No leading spaces - wait for reset - while line is not None: - line = (yield line) - - -_assign_pat = \ -r'''(?P<lhs>(\s*) - ([\w\.]+) # Initial identifier - (\s*,\s* - \*?[\w\.]+)* # Further identifiers for unpacking - \s*?,? # Trailing comma - ) - \s*=\s* -''' - -assign_system_re = re.compile(r'{}!\s*(?P<cmd>.*)'.format(_assign_pat), re.VERBOSE) -assign_system_template = '%s = get_ipython().getoutput(%r)' -@StatelessInputTransformer.wrap -def assign_from_system(line): - """Transform assignment from system commands (e.g. files = !ls)""" - m = assign_system_re.match(line) - if m is None: - return line - - return assign_system_template % m.group('lhs', 'cmd') - -assign_magic_re = re.compile(r'{}%\s*(?P<cmd>.*)'.format(_assign_pat), re.VERBOSE) -assign_magic_template = '%s = get_ipython().run_line_magic(%r, %r)' -@StatelessInputTransformer.wrap -def assign_from_magic(line): - """Transform assignment from magic commands (e.g. a = %who_ls)""" - m = assign_magic_re.match(line) - if m is None: - return line - #Prepare arguments for get_ipython().run_line_magic(magic_name, magic_args) - m_lhs, m_cmd = m.group('lhs', 'cmd') - t_magic_name, _, t_magic_arg_s = m_cmd.partition(' ') - t_magic_name = t_magic_name.lstrip(ESC_MAGIC) - return assign_magic_template % (m_lhs, t_magic_name, t_magic_arg_s) diff --git a/contrib/python/ipython/py3/IPython/core/inputtransformer2.py b/contrib/python/ipython/py3/IPython/core/inputtransformer2.py deleted file mode 100644 index a8f676f495..0000000000 --- a/contrib/python/ipython/py3/IPython/core/inputtransformer2.py +++ /dev/null @@ -1,788 +0,0 @@ -"""Input transformer machinery to support IPython special syntax. - -This includes the machinery to recognise and transform ``%magic`` commands, -``!system`` commands, ``help?`` querying, prompt stripping, and so forth. - -Added: IPython 7.0. Replaces inputsplitter and inputtransformer which were -deprecated in 7.0. -""" - -# Copyright (c) IPython Development Team. -# Distributed under the terms of the Modified BSD License. - -import ast -import sys -from codeop import CommandCompiler, Compile -import re -import tokenize -from typing import List, Tuple, Optional, Any -import warnings - -_indent_re = re.compile(r'^[ \t]+') - -def leading_empty_lines(lines): - """Remove leading empty lines - - If the leading lines are empty or contain only whitespace, they will be - removed. - """ - if not lines: - return lines - for i, line in enumerate(lines): - if line and not line.isspace(): - return lines[i:] - return lines - -def leading_indent(lines): - """Remove leading indentation. - - If the first line starts with a spaces or tabs, the same whitespace will be - removed from each following line in the cell. - """ - if not lines: - return lines - m = _indent_re.match(lines[0]) - if not m: - return lines - space = m.group(0) - n = len(space) - return [l[n:] if l.startswith(space) else l - for l in lines] - -class PromptStripper: - """Remove matching input prompts from a block of input. - - Parameters - ---------- - prompt_re : regular expression - A regular expression matching any input prompt (including continuation, - e.g. ``...``) - initial_re : regular expression, optional - A regular expression matching only the initial prompt, but not continuation. - If no initial expression is given, prompt_re will be used everywhere. - Used mainly for plain Python prompts (``>>>``), where the continuation prompt - ``...`` is a valid Python expression in Python 3, so shouldn't be stripped. - - Notes - ----- - - If initial_re and prompt_re differ, - only initial_re will be tested against the first line. - If any prompt is found on the first two lines, - prompts will be stripped from the rest of the block. - """ - def __init__(self, prompt_re, initial_re=None): - self.prompt_re = prompt_re - self.initial_re = initial_re or prompt_re - - def _strip(self, lines): - return [self.prompt_re.sub('', l, count=1) for l in lines] - - def __call__(self, lines): - if not lines: - return lines - if self.initial_re.match(lines[0]) or \ - (len(lines) > 1 and self.prompt_re.match(lines[1])): - return self._strip(lines) - return lines - -classic_prompt = PromptStripper( - prompt_re=re.compile(r'^(>>>|\.\.\.)( |$)'), - initial_re=re.compile(r'^>>>( |$)') -) - -ipython_prompt = PromptStripper( - re.compile( - r""" - ^( # Match from the beginning of a line, either: - - # 1. First-line prompt: - ((\[nav\]|\[ins\])?\ )? # Vi editing mode prompt, if it's there - In\ # The 'In' of the prompt, with a space - \[\d+\]: # Command index, as displayed in the prompt - \ # With a mandatory trailing space - - | # ... or ... - - # 2. The three dots of the multiline prompt - \s* # All leading whitespace characters - \.{3,}: # The three (or more) dots - \ ? # With an optional trailing space - - ) - """, - re.VERBOSE, - ) -) - - -def cell_magic(lines): - if not lines or not lines[0].startswith('%%'): - return lines - if re.match(r'%%\w+\?', lines[0]): - # This case will be handled by help_end - return lines - magic_name, _, first_line = lines[0][2:].rstrip().partition(' ') - body = ''.join(lines[1:]) - return ['get_ipython().run_cell_magic(%r, %r, %r)\n' - % (magic_name, first_line, body)] - - -def _find_assign_op(token_line) -> Optional[int]: - """Get the index of the first assignment in the line ('=' not inside brackets) - - Note: We don't try to support multiple special assignment (a = b = %foo) - """ - paren_level = 0 - for i, ti in enumerate(token_line): - s = ti.string - if s == '=' and paren_level == 0: - return i - if s in {'(','[','{'}: - paren_level += 1 - elif s in {')', ']', '}'}: - if paren_level > 0: - paren_level -= 1 - return None - -def find_end_of_continued_line(lines, start_line: int): - """Find the last line of a line explicitly extended using backslashes. - - Uses 0-indexed line numbers. - """ - end_line = start_line - while lines[end_line].endswith('\\\n'): - end_line += 1 - if end_line >= len(lines): - break - return end_line - -def assemble_continued_line(lines, start: Tuple[int, int], end_line: int): - r"""Assemble a single line from multiple continued line pieces - - Continued lines are lines ending in ``\``, and the line following the last - ``\`` in the block. - - For example, this code continues over multiple lines:: - - if (assign_ix is not None) \ - and (len(line) >= assign_ix + 2) \ - and (line[assign_ix+1].string == '%') \ - and (line[assign_ix+2].type == tokenize.NAME): - - This statement contains four continued line pieces. - Assembling these pieces into a single line would give:: - - if (assign_ix is not None) and (len(line) >= assign_ix + 2) and (line[... - - This uses 0-indexed line numbers. *start* is (lineno, colno). - - Used to allow ``%magic`` and ``!system`` commands to be continued over - multiple lines. - """ - parts = [lines[start[0]][start[1]:]] + lines[start[0]+1:end_line+1] - return ' '.join([p.rstrip()[:-1] for p in parts[:-1]] # Strip backslash+newline - + [parts[-1].rstrip()]) # Strip newline from last line - -class TokenTransformBase: - """Base class for transformations which examine tokens. - - Special syntax should not be transformed when it occurs inside strings or - comments. This is hard to reliably avoid with regexes. The solution is to - tokenise the code as Python, and recognise the special syntax in the tokens. - - IPython's special syntax is not valid Python syntax, so tokenising may go - wrong after the special syntax starts. These classes therefore find and - transform *one* instance of special syntax at a time into regular Python - syntax. After each transformation, tokens are regenerated to find the next - piece of special syntax. - - Subclasses need to implement one class method (find) - and one regular method (transform). - - The priority attribute can select which transformation to apply if multiple - transformers match in the same place. Lower numbers have higher priority. - This allows "%magic?" to be turned into a help call rather than a magic call. - """ - # Lower numbers -> higher priority (for matches in the same location) - priority = 10 - - def sortby(self): - return self.start_line, self.start_col, self.priority - - def __init__(self, start): - self.start_line = start[0] - 1 # Shift from 1-index to 0-index - self.start_col = start[1] - - @classmethod - def find(cls, tokens_by_line): - """Find one instance of special syntax in the provided tokens. - - Tokens are grouped into logical lines for convenience, - so it is easy to e.g. look at the first token of each line. - *tokens_by_line* is a list of lists of tokenize.TokenInfo objects. - - This should return an instance of its class, pointing to the start - position it has found, or None if it found no match. - """ - raise NotImplementedError - - def transform(self, lines: List[str]): - """Transform one instance of special syntax found by ``find()`` - - Takes a list of strings representing physical lines, - returns a similar list of transformed lines. - """ - raise NotImplementedError - -class MagicAssign(TokenTransformBase): - """Transformer for assignments from magics (a = %foo)""" - @classmethod - def find(cls, tokens_by_line): - """Find the first magic assignment (a = %foo) in the cell. - """ - for line in tokens_by_line: - assign_ix = _find_assign_op(line) - if (assign_ix is not None) \ - and (len(line) >= assign_ix + 2) \ - and (line[assign_ix+1].string == '%') \ - and (line[assign_ix+2].type == tokenize.NAME): - return cls(line[assign_ix+1].start) - - def transform(self, lines: List[str]): - """Transform a magic assignment found by the ``find()`` classmethod. - """ - start_line, start_col = self.start_line, self.start_col - lhs = lines[start_line][:start_col] - end_line = find_end_of_continued_line(lines, start_line) - rhs = assemble_continued_line(lines, (start_line, start_col), end_line) - assert rhs.startswith('%'), rhs - magic_name, _, args = rhs[1:].partition(' ') - - lines_before = lines[:start_line] - call = "get_ipython().run_line_magic({!r}, {!r})".format(magic_name, args) - new_line = lhs + call + '\n' - lines_after = lines[end_line+1:] - - return lines_before + [new_line] + lines_after - - -class SystemAssign(TokenTransformBase): - """Transformer for assignments from system commands (a = !foo)""" - @classmethod - def find(cls, tokens_by_line): - """Find the first system assignment (a = !foo) in the cell. - """ - for line in tokens_by_line: - assign_ix = _find_assign_op(line) - if (assign_ix is not None) \ - and not line[assign_ix].line.strip().startswith('=') \ - and (len(line) >= assign_ix + 2) \ - and (line[assign_ix + 1].type == tokenize.ERRORTOKEN): - ix = assign_ix + 1 - - while ix < len(line) and line[ix].type == tokenize.ERRORTOKEN: - if line[ix].string == '!': - return cls(line[ix].start) - elif not line[ix].string.isspace(): - break - ix += 1 - - def transform(self, lines: List[str]): - """Transform a system assignment found by the ``find()`` classmethod. - """ - start_line, start_col = self.start_line, self.start_col - - lhs = lines[start_line][:start_col] - end_line = find_end_of_continued_line(lines, start_line) - rhs = assemble_continued_line(lines, (start_line, start_col), end_line) - assert rhs.startswith('!'), rhs - cmd = rhs[1:] - - lines_before = lines[:start_line] - call = "get_ipython().getoutput({!r})".format(cmd) - new_line = lhs + call + '\n' - lines_after = lines[end_line + 1:] - - return lines_before + [new_line] + lines_after - -# The escape sequences that define the syntax transformations IPython will -# apply to user input. These can NOT be just changed here: many regular -# expressions and other parts of the code may use their hardcoded values, and -# for all intents and purposes they constitute the 'IPython syntax', so they -# should be considered fixed. - -ESC_SHELL = '!' # Send line to underlying system shell -ESC_SH_CAP = '!!' # Send line to system shell and capture output -ESC_HELP = '?' # Find information about object -ESC_HELP2 = '??' # Find extra-detailed information about object -ESC_MAGIC = '%' # Call magic function -ESC_MAGIC2 = '%%' # Call cell-magic function -ESC_QUOTE = ',' # Split args on whitespace, quote each as string and call -ESC_QUOTE2 = ';' # Quote all args as a single string, call -ESC_PAREN = '/' # Call first argument with rest of line as arguments - -ESCAPE_SINGLES = {'!', '?', '%', ',', ';', '/'} -ESCAPE_DOUBLES = {'!!', '??'} # %% (cell magic) is handled separately - -def _make_help_call(target, esc): - """Prepares a pinfo(2)/psearch call from a target name and the escape - (i.e. ? or ??)""" - method = 'pinfo2' if esc == '??' \ - else 'psearch' if '*' in target \ - else 'pinfo' - arg = " ".join([method, target]) - #Prepare arguments for get_ipython().run_line_magic(magic_name, magic_args) - t_magic_name, _, t_magic_arg_s = arg.partition(' ') - t_magic_name = t_magic_name.lstrip(ESC_MAGIC) - return "get_ipython().run_line_magic(%r, %r)" % (t_magic_name, t_magic_arg_s) - - -def _tr_help(content): - """Translate lines escaped with: ? - - A naked help line should fire the intro help screen (shell.show_usage()) - """ - if not content: - return 'get_ipython().show_usage()' - - return _make_help_call(content, '?') - -def _tr_help2(content): - """Translate lines escaped with: ?? - - A naked help line should fire the intro help screen (shell.show_usage()) - """ - if not content: - return 'get_ipython().show_usage()' - - return _make_help_call(content, '??') - -def _tr_magic(content): - "Translate lines escaped with a percent sign: %" - name, _, args = content.partition(' ') - return 'get_ipython().run_line_magic(%r, %r)' % (name, args) - -def _tr_quote(content): - "Translate lines escaped with a comma: ," - name, _, args = content.partition(' ') - return '%s("%s")' % (name, '", "'.join(args.split()) ) - -def _tr_quote2(content): - "Translate lines escaped with a semicolon: ;" - name, _, args = content.partition(' ') - return '%s("%s")' % (name, args) - -def _tr_paren(content): - "Translate lines escaped with a slash: /" - name, _, args = content.partition(' ') - return '%s(%s)' % (name, ", ".join(args.split())) - -tr = { ESC_SHELL : 'get_ipython().system({!r})'.format, - ESC_SH_CAP : 'get_ipython().getoutput({!r})'.format, - ESC_HELP : _tr_help, - ESC_HELP2 : _tr_help2, - ESC_MAGIC : _tr_magic, - ESC_QUOTE : _tr_quote, - ESC_QUOTE2 : _tr_quote2, - ESC_PAREN : _tr_paren } - -class EscapedCommand(TokenTransformBase): - """Transformer for escaped commands like %foo, !foo, or /foo""" - @classmethod - def find(cls, tokens_by_line): - """Find the first escaped command (%foo, !foo, etc.) in the cell. - """ - for line in tokens_by_line: - if not line: - continue - ix = 0 - ll = len(line) - while ll > ix and line[ix].type in {tokenize.INDENT, tokenize.DEDENT}: - ix += 1 - if ix >= ll: - continue - if line[ix].string in ESCAPE_SINGLES: - return cls(line[ix].start) - - def transform(self, lines): - """Transform an escaped line found by the ``find()`` classmethod. - """ - start_line, start_col = self.start_line, self.start_col - - indent = lines[start_line][:start_col] - end_line = find_end_of_continued_line(lines, start_line) - line = assemble_continued_line(lines, (start_line, start_col), end_line) - - if len(line) > 1 and line[:2] in ESCAPE_DOUBLES: - escape, content = line[:2], line[2:] - else: - escape, content = line[:1], line[1:] - - if escape in tr: - call = tr[escape](content) - else: - call = '' - - lines_before = lines[:start_line] - new_line = indent + call + '\n' - lines_after = lines[end_line + 1:] - - return lines_before + [new_line] + lines_after - -_help_end_re = re.compile(r"""(%{0,2} - (?!\d)[\w*]+ # Variable name - (\.(?!\d)[\w*]+)* # .etc.etc - ) - (\?\??)$ # ? or ?? - """, - re.VERBOSE) - -class HelpEnd(TokenTransformBase): - """Transformer for help syntax: obj? and obj??""" - # This needs to be higher priority (lower number) than EscapedCommand so - # that inspecting magics (%foo?) works. - priority = 5 - - def __init__(self, start, q_locn): - super().__init__(start) - self.q_line = q_locn[0] - 1 # Shift from 1-indexed to 0-indexed - self.q_col = q_locn[1] - - @classmethod - def find(cls, tokens_by_line): - """Find the first help command (foo?) in the cell. - """ - for line in tokens_by_line: - # Last token is NEWLINE; look at last but one - if len(line) > 2 and line[-2].string == '?': - # Find the first token that's not INDENT/DEDENT - ix = 0 - while line[ix].type in {tokenize.INDENT, tokenize.DEDENT}: - ix += 1 - return cls(line[ix].start, line[-2].start) - - def transform(self, lines): - """Transform a help command found by the ``find()`` classmethod. - """ - piece = ''.join(lines[self.start_line:self.q_line+1]) - indent, content = piece[:self.start_col], piece[self.start_col:] - lines_before = lines[:self.start_line] - lines_after = lines[self.q_line + 1:] - - m = _help_end_re.search(content) - if not m: - raise SyntaxError(content) - assert m is not None, content - target = m.group(1) - esc = m.group(3) - - - call = _make_help_call(target, esc) - new_line = indent + call + '\n' - - return lines_before + [new_line] + lines_after - -def make_tokens_by_line(lines:List[str]): - """Tokenize a series of lines and group tokens by line. - - The tokens for a multiline Python string or expression are grouped as one - line. All lines except the last lines should keep their line ending ('\\n', - '\\r\\n') for this to properly work. Use `.splitlines(keeplineending=True)` - for example when passing block of text to this function. - - """ - # NL tokens are used inside multiline expressions, but also after blank - # lines or comments. This is intentional - see https://bugs.python.org/issue17061 - # We want to group the former case together but split the latter, so we - # track parentheses level, similar to the internals of tokenize. - - # reexported from token on 3.7+ - NEWLINE, NL = tokenize.NEWLINE, tokenize.NL # type: ignore - tokens_by_line: List[List[Any]] = [[]] - if len(lines) > 1 and not lines[0].endswith(("\n", "\r", "\r\n", "\x0b", "\x0c")): - warnings.warn( - "`make_tokens_by_line` received a list of lines which do not have lineending markers ('\\n', '\\r', '\\r\\n', '\\x0b', '\\x0c'), behavior will be unspecified", - stacklevel=2, - ) - parenlev = 0 - try: - for token in tokenize.generate_tokens(iter(lines).__next__): - tokens_by_line[-1].append(token) - if (token.type == NEWLINE) \ - or ((token.type == NL) and (parenlev <= 0)): - tokens_by_line.append([]) - elif token.string in {'(', '[', '{'}: - parenlev += 1 - elif token.string in {')', ']', '}'}: - if parenlev > 0: - parenlev -= 1 - except tokenize.TokenError: - # Input ended in a multiline string or expression. That's OK for us. - pass - - - if not tokens_by_line[-1]: - tokens_by_line.pop() - - - return tokens_by_line - - -def has_sunken_brackets(tokens: List[tokenize.TokenInfo]): - """Check if the depth of brackets in the list of tokens drops below 0""" - parenlev = 0 - for token in tokens: - if token.string in {"(", "[", "{"}: - parenlev += 1 - elif token.string in {")", "]", "}"}: - parenlev -= 1 - if parenlev < 0: - return True - return False - - -def show_linewise_tokens(s: str): - """For investigation and debugging""" - if not s.endswith('\n'): - s += '\n' - lines = s.splitlines(keepends=True) - for line in make_tokens_by_line(lines): - print("Line -------") - for tokinfo in line: - print(" ", tokinfo) - -# Arbitrary limit to prevent getting stuck in infinite loops -TRANSFORM_LOOP_LIMIT = 500 - -class TransformerManager: - """Applies various transformations to a cell or code block. - - The key methods for external use are ``transform_cell()`` - and ``check_complete()``. - """ - def __init__(self): - self.cleanup_transforms = [ - leading_empty_lines, - leading_indent, - classic_prompt, - ipython_prompt, - ] - self.line_transforms = [ - cell_magic, - ] - self.token_transformers = [ - MagicAssign, - SystemAssign, - EscapedCommand, - HelpEnd, - ] - - def do_one_token_transform(self, lines): - """Find and run the transform earliest in the code. - - Returns (changed, lines). - - This method is called repeatedly until changed is False, indicating - that all available transformations are complete. - - The tokens following IPython special syntax might not be valid, so - the transformed code is retokenised every time to identify the next - piece of special syntax. Hopefully long code cells are mostly valid - Python, not using lots of IPython special syntax, so this shouldn't be - a performance issue. - """ - tokens_by_line = make_tokens_by_line(lines) - candidates = [] - for transformer_cls in self.token_transformers: - transformer = transformer_cls.find(tokens_by_line) - if transformer: - candidates.append(transformer) - - if not candidates: - # Nothing to transform - return False, lines - ordered_transformers = sorted(candidates, key=TokenTransformBase.sortby) - for transformer in ordered_transformers: - try: - return True, transformer.transform(lines) - except SyntaxError: - pass - return False, lines - - def do_token_transforms(self, lines): - for _ in range(TRANSFORM_LOOP_LIMIT): - changed, lines = self.do_one_token_transform(lines) - if not changed: - return lines - - raise RuntimeError("Input transformation still changing after " - "%d iterations. Aborting." % TRANSFORM_LOOP_LIMIT) - - def transform_cell(self, cell: str) -> str: - """Transforms a cell of input code""" - if not cell.endswith('\n'): - cell += '\n' # Ensure the cell has a trailing newline - lines = cell.splitlines(keepends=True) - for transform in self.cleanup_transforms + self.line_transforms: - lines = transform(lines) - - lines = self.do_token_transforms(lines) - return ''.join(lines) - - def check_complete(self, cell: str): - """Return whether a block of code is ready to execute, or should be continued - - Parameters - ---------- - cell : string - Python input code, which can be multiline. - - Returns - ------- - status : str - One of 'complete', 'incomplete', or 'invalid' if source is not a - prefix of valid code. - indent_spaces : int or None - The number of spaces by which to indent the next line of code. If - status is not 'incomplete', this is None. - """ - # Remember if the lines ends in a new line. - ends_with_newline = False - for character in reversed(cell): - if character == '\n': - ends_with_newline = True - break - elif character.strip(): - break - else: - continue - - if not ends_with_newline: - # Append an newline for consistent tokenization - # See https://bugs.python.org/issue33899 - cell += '\n' - - lines = cell.splitlines(keepends=True) - - if not lines: - return 'complete', None - - if lines[-1].endswith('\\'): - # Explicit backslash continuation - return 'incomplete', find_last_indent(lines) - - try: - for transform in self.cleanup_transforms: - if not getattr(transform, 'has_side_effects', False): - lines = transform(lines) - except SyntaxError: - return 'invalid', None - - if lines[0].startswith('%%'): - # Special case for cell magics - completion marked by blank line - if lines[-1].strip(): - return 'incomplete', find_last_indent(lines) - else: - return 'complete', None - - try: - for transform in self.line_transforms: - if not getattr(transform, 'has_side_effects', False): - lines = transform(lines) - lines = self.do_token_transforms(lines) - except SyntaxError: - return 'invalid', None - - tokens_by_line = make_tokens_by_line(lines) - - # Bail if we got one line and there are more closing parentheses than - # the opening ones - if ( - len(lines) == 1 - and tokens_by_line - and has_sunken_brackets(tokens_by_line[0]) - ): - return "invalid", None - - if not tokens_by_line: - return 'incomplete', find_last_indent(lines) - - if tokens_by_line[-1][-1].type != tokenize.ENDMARKER: - # We're in a multiline string or expression - return 'incomplete', find_last_indent(lines) - - newline_types = {tokenize.NEWLINE, tokenize.COMMENT, tokenize.ENDMARKER} # type: ignore - - # Pop the last line which only contains DEDENTs and ENDMARKER - last_token_line = None - if {t.type for t in tokens_by_line[-1]} in [ - {tokenize.DEDENT, tokenize.ENDMARKER}, - {tokenize.ENDMARKER} - ] and len(tokens_by_line) > 1: - last_token_line = tokens_by_line.pop() - - while tokens_by_line[-1] and tokens_by_line[-1][-1].type in newline_types: - tokens_by_line[-1].pop() - - if not tokens_by_line[-1]: - return 'incomplete', find_last_indent(lines) - - if tokens_by_line[-1][-1].string == ':': - # The last line starts a block (e.g. 'if foo:') - ix = 0 - while tokens_by_line[-1][ix].type in {tokenize.INDENT, tokenize.DEDENT}: - ix += 1 - - indent = tokens_by_line[-1][ix].start[1] - return 'incomplete', indent + 4 - - if tokens_by_line[-1][0].line.endswith('\\'): - return 'incomplete', None - - # At this point, our checks think the code is complete (or invalid). - # We'll use codeop.compile_command to check this with the real parser - try: - with warnings.catch_warnings(): - warnings.simplefilter('error', SyntaxWarning) - res = compile_command(''.join(lines), symbol='exec') - except (SyntaxError, OverflowError, ValueError, TypeError, - MemoryError, SyntaxWarning): - return 'invalid', None - else: - if res is None: - return 'incomplete', find_last_indent(lines) - - if last_token_line and last_token_line[0].type == tokenize.DEDENT: - if ends_with_newline: - return 'complete', None - return 'incomplete', find_last_indent(lines) - - # If there's a blank line at the end, assume we're ready to execute - if not lines[-1].strip(): - return 'complete', None - - return 'complete', None - - -def find_last_indent(lines): - m = _indent_re.match(lines[-1]) - if not m: - return 0 - return len(m.group(0).replace('\t', ' '*4)) - - -class MaybeAsyncCompile(Compile): - def __init__(self, extra_flags=0): - super().__init__() - self.flags |= extra_flags - - -class MaybeAsyncCommandCompiler(CommandCompiler): - def __init__(self, extra_flags=0): - self.compiler = MaybeAsyncCompile(extra_flags=extra_flags) - - -_extra_flags = ast.PyCF_ALLOW_TOP_LEVEL_AWAIT - -compile_command = MaybeAsyncCommandCompiler(extra_flags=_extra_flags) diff --git a/contrib/python/ipython/py3/IPython/core/interactiveshell.py b/contrib/python/ipython/py3/IPython/core/interactiveshell.py deleted file mode 100644 index 371a3dad77..0000000000 --- a/contrib/python/ipython/py3/IPython/core/interactiveshell.py +++ /dev/null @@ -1,3800 +0,0 @@ -# -*- coding: utf-8 -*- -"""Main IPython class.""" - -#----------------------------------------------------------------------------- -# Copyright (C) 2001 Janko Hauser <jhauser@zscout.de> -# Copyright (C) 2001-2007 Fernando Perez. <fperez@colorado.edu> -# Copyright (C) 2008-2011 The IPython Development Team -# -# Distributed under the terms of the BSD License. The full license is in -# the file COPYING, distributed as part of this software. -#----------------------------------------------------------------------------- - - -import abc -import ast -import atexit -import bdb -import builtins as builtin_mod -import dis -import functools -import inspect -import os -import re -import runpy -import subprocess -import sys -import tempfile -import traceback -import types -import warnings -from ast import stmt -from io import open as io_open -from logging import error -from pathlib import Path -from typing import Callable -from typing import List as ListType -from typing import Optional, Tuple -from warnings import warn - -from pickleshare import PickleShareDB -from tempfile import TemporaryDirectory -from traitlets import ( - Any, - Bool, - CaselessStrEnum, - Dict, - Enum, - Instance, - Integer, - List, - Type, - Unicode, - default, - observe, - validate, -) -from traitlets.config.configurable import SingletonConfigurable -from traitlets.utils.importstring import import_item - -import IPython.core.hooks -from IPython.core import magic, oinspect, page, prefilter, ultratb -from IPython.core.alias import Alias, AliasManager -from IPython.core.autocall import ExitAutocall -from IPython.core.builtin_trap import BuiltinTrap -from IPython.core.compilerop import CachingCompiler, check_linecache_ipython -from IPython.core.debugger import InterruptiblePdb -from IPython.core.display_trap import DisplayTrap -from IPython.core.displayhook import DisplayHook -from IPython.core.displaypub import DisplayPublisher -from IPython.core.error import InputRejected, UsageError -from IPython.core.events import EventManager, available_events -from IPython.core.extensions import ExtensionManager -from IPython.core.formatters import DisplayFormatter -from IPython.core.history import HistoryManager -from IPython.core.inputtransformer2 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.display import display -from IPython.paths import get_ipython_dir -from IPython.testing.skipdoctest import skip_doctest -from IPython.utils import PyColorize, io, openpy, py3compat -from IPython.utils.decorators import undoc -from IPython.utils.io import ask_yes_no -from IPython.utils.ipstruct import Struct -from IPython.utils.path import ensure_dir_exists, get_home_dir, get_py_filename -from IPython.utils.process import getoutput, system -from IPython.utils.strdispatch import StrDispatch -from IPython.utils.syspathcontext import prepended_to_syspath -from IPython.utils.text import DollarFormatter, LSString, SList, format_screen - -sphinxify: Optional[Callable] - -try: - import docrepr.sphinxify as sphx - - def sphinxify(oinfo): - wrapped_docstring = sphx.wrap_main_docstring(oinfo) - - def sphinxify_docstring(docstring): - with TemporaryDirectory() as dirname: - return { - "text/html": sphx.sphinxify(wrapped_docstring, dirname), - "text/plain": docstring, - } - - return sphinxify_docstring -except ImportError: - sphinxify = None - - -class ProvisionalWarning(DeprecationWarning): - """ - Warning class for unstable features - """ - pass - -from ast import Module - -_assign_nodes = (ast.AugAssign, ast.AnnAssign, ast.Assign) -_single_targets_nodes = (ast.AugAssign, ast.AnnAssign) - -#----------------------------------------------------------------------------- -# Await Helpers -#----------------------------------------------------------------------------- - -# we still need to run things using the asyncio eventloop, but there is no -# async integration -from .async_helpers import ( - _asyncio_runner, - _curio_runner, - _pseudo_sync_runner, - _should_be_async, - _trio_runner, -) - -#----------------------------------------------------------------------------- -# Globals -#----------------------------------------------------------------------------- - -# compiled regexps for autoindent management -dedent_re = re.compile(r'^\s+raise|^\s+return|^\s+pass') - -#----------------------------------------------------------------------------- -# Utilities -#----------------------------------------------------------------------------- - -@undoc -def softspace(file, newvalue): - """Copied from code.py, to remove the dependency""" - - oldvalue = 0 - try: - oldvalue = file.softspace - except AttributeError: - pass - try: - file.softspace = newvalue - except (AttributeError, TypeError): - # "attribute-less object" or "read-only attributes" - pass - return oldvalue - -@undoc -def no_op(*a, **kw): - pass - - -class SpaceInInput(Exception): pass - - -class SeparateUnicode(Unicode): - r"""A Unicode subclass to validate separate_in, separate_out, etc. - - This is a Unicode based trait that converts '0'->'' and ``'\\n'->'\n'``. - """ - - def validate(self, obj, value): - if value == '0': value = '' - value = value.replace('\\n','\n') - return super(SeparateUnicode, self).validate(obj, value) - - -@undoc -class DummyMod(object): - """A dummy module used for IPython's interactive module when - a namespace must be assigned to the module's __dict__.""" - __spec__ = None - - -class ExecutionInfo(object): - """The arguments used for a call to :meth:`InteractiveShell.run_cell` - - Stores information about what is going to happen. - """ - raw_cell = None - store_history = False - silent = False - shell_futures = True - cell_id = None - - def __init__(self, raw_cell, store_history, silent, shell_futures, cell_id): - self.raw_cell = raw_cell - self.store_history = store_history - self.silent = silent - self.shell_futures = shell_futures - self.cell_id = cell_id - - def __repr__(self): - name = self.__class__.__qualname__ - raw_cell = ( - (self.raw_cell[:50] + "..") if len(self.raw_cell) > 50 else self.raw_cell - ) - return '<%s object at %x, raw_cell="%s" store_history=%s silent=%s shell_futures=%s cell_id=%s>' % ( - name, - id(self), - raw_cell, - self.store_history, - self.silent, - self.shell_futures, - self.cell_id, - ) - - -class ExecutionResult(object): - """The result of a call to :meth:`InteractiveShell.run_cell` - - Stores information about what took place. - """ - execution_count = None - error_before_exec = None - error_in_exec: Optional[BaseException] = None - info = None - result = None - - def __init__(self, info): - self.info = info - - @property - def success(self): - return (self.error_before_exec is None) and (self.error_in_exec is None) - - def raise_error(self): - """Reraises error if `success` is `False`, otherwise does nothing""" - if self.error_before_exec is not None: - raise self.error_before_exec - if self.error_in_exec is not None: - raise self.error_in_exec - - def __repr__(self): - name = self.__class__.__qualname__ - return '<%s object at %x, execution_count=%s error_before_exec=%s error_in_exec=%s info=%s result=%s>' %\ - (name, id(self), self.execution_count, self.error_before_exec, self.error_in_exec, repr(self.info), repr(self.result)) - - -class InteractiveShell(SingletonConfigurable): - """An enhanced, interactive shell for Python.""" - - _instance = None - - 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) - - 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)' - automatically. The value can be '0' to disable the feature, '1' for - 'smart' autocall, where it is not applied if there are no more - 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) - - autoindent = Bool(True, help= - """ - Autoindent IPython code entered interactively. - """ - ).tag(config=True) - - autoawait = Bool(True, help= - """ - Automatically run await statement in the top level repl. - """ - ).tag(config=True) - - loop_runner_map ={ - 'asyncio':(_asyncio_runner, True), - 'curio':(_curio_runner, True), - 'trio':(_trio_runner, True), - 'sync': (_pseudo_sync_runner, False) - } - - loop_runner = Any(default_value="IPython.core.interactiveshell._asyncio_runner", - allow_none=True, - help="""Select the loop runner that will be used to execute top-level asynchronous code""" - ).tag(config=True) - - @default('loop_runner') - def _default_loop_runner(self): - return import_item("IPython.core.interactiveshell._asyncio_runner") - - @validate('loop_runner') - def _import_runner(self, proposal): - if isinstance(proposal.value, str): - if proposal.value in self.loop_runner_map: - runner, autoawait = self.loop_runner_map[proposal.value] - self.autoawait = autoawait - return runner - runner = import_item(proposal.value) - if not callable(runner): - raise ValueError('loop_runner must be callable') - return runner - if not callable(proposal.value): - raise ValueError('loop_runner must be callable') - return proposal.value - - automagic = Bool(True, help= - """ - Enable magic commands to be called without the leading %. - """ - ).tag(config=True) - - banner1 = Unicode(default_banner, - help="""The part of the banner to be printed before the profile""" - ).tag(config=True) - banner2 = Unicode('', - help="""The part of the banner to be printed after the profile""" - ).tag(config=True) - - 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 - disables the caching system, and the minimum value accepted is 3 (if - you provide a value less than 3, it is reset to 0 and a warning is - 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= - """ - 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) - disable_failing_post_execute = Bool(False, - help="Don't call post-execute functions that have failed in the past." - ).tag(config=True) - display_formatter = Instance(DisplayFormatter, allow_none=True) - displayhook_class = Type(DisplayHook) - display_pub_class = Type(DisplayPublisher) - compiler_class = Type(CachingCompiler) - - 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) - exiter = Instance(ExitAutocall) - @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__ - - # Used to transform cells before running them, and check whether code is complete - input_transformer_manager = Instance('IPython.core.inputtransformer2.TransformerManager', - ()) - - @property - def input_transformers_cleanup(self): - return self.input_transformer_manager.cleanup_transforms - - input_transformers_post = List([], - help="A list of string input transformers, to be applied after IPython's " - "own input transformations." - ) - - @property - def input_splitter(self): - """Make this available for backward compatibility (pre-7.0 release) with existing code. - - For example, ipykernel ipykernel currently uses - `shell.input_splitter.check_complete` - """ - from warnings import warn - warn("`input_splitter` is deprecated since IPython 7.0, prefer `input_transformer_manager`.", - DeprecationWarning, stacklevel=2 - ) - return self.input_transformer_manager - - 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= - """ - The name of the logfile to use. - """ - ).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) - object_info_string_level = Enum((0,1,2), default_value=0, - ).tag(config=True) - pdb = Bool(False, help= - """ - Automatically call the pdb debugger after every exception. - """ - ).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) - - - show_rewritten_input = Bool(True, - help="Show rewritten input, e.g. for autocall." - ).tag(config=True) - - quiet = Bool(False).tag(config=True) - - history_length = Integer(10000, - help='Total length of command history' - ).tag(config=True) - - history_load_length = Integer(1000, help= - """ - The number of saved history entries to be loaded - into the history buffer at startup. - """ - ).tag(config=True) - - ast_node_interactivity = Enum(['all', 'last', 'last_expr', 'none', 'last_expr_or_assign'], - default_value='last_expr', - help=""" - 'all', 'last', 'last_expr' or 'none', 'last_expr_or_assign' specifying - which nodes should be 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) - xmode = CaselessStrEnum(('Context', 'Plain', 'Verbose', 'Minimal'), - default_value='Context', - help="Switch modes for the IPython exception handlers." - ).tag(config=True) - - # Subcomponents of InteractiveShell - alias_manager = Instance('IPython.core.alias.AliasManager', allow_none=True) - prefilter_manager = Instance('IPython.core.prefilter.PrefilterManager', allow_none=True) - builtin_trap = Instance('IPython.core.builtin_trap.BuiltinTrap', allow_none=True) - display_trap = Instance('IPython.core.display_trap.DisplayTrap', allow_none=True) - extension_manager = Instance('IPython.core.extensions.ExtensionManager', allow_none=True) - payload_manager = Instance('IPython.core.payload.PayloadManager', allow_none=True) - history_manager = Instance('IPython.core.history.HistoryAccessorBase', allow_none=True) - magics_manager = Instance('IPython.core.magic.MagicsManager', allow_none=True) - - profile_dir = Instance('IPython.core.application.ProfileDir', allow_none=True) - @property - def profile(self): - if self.profile_dir is not None: - name = os.path.basename(self.profile_dir.location) - return name.replace('profile_','') - - - # Private interface - _post_execute = Dict() - - # Tracks any GUI loop loaded for pylab - pylab_gui_select = None - - last_execution_succeeded = Bool(True, help='Did last executed command succeeded') - - last_execution_result = Instance('IPython.core.interactiveshell.ExecutionResult', help='Result of executing the last command', allow_none=True) - - def __init__(self, ipython_dir=None, profile_dir=None, - user_module=None, user_ns=None, - custom_exceptions=((), None), **kwargs): - # 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') - self.configurables = [self] - - # These are relatively independent and stateless - self.init_ipython_dir(ipython_dir) - 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() - - # Create namespaces (user_ns, user_global_ns, etc.) - self.init_create_namespaces(user_module, user_ns) - # This has to be done after init_create_namespaces because it uses - # something in self.user_ns, but before init_sys_modules, which - # is the first thing to modify sys. - # TODO: When we override sys.stdout and sys.stderr before this class - # is created, we are saving the overridden ones here. Not sure if this - # is what we want to do. - self.save_sys_module_state() - self.init_sys_modules() - - # While we're trying to have each part of the code directly access what - # it needs without keeping redundant references to objects, we have too - # much legacy code that expects ip.db to exist. - self.db = PickleShareDB(os.path.join(self.profile_dir.location, 'db')) - - self.init_history() - self.init_encoding() - self.init_prefilter() - - self.init_syntax_highlighting() - self.init_hooks() - self.init_events() - self.init_pushd_popd_magic() - self.init_user_ns() - self.init_logger() - self.init_builtins() - - # The following was in post_config_initialization - self.init_inspector() - self.raw_input_original = input - self.init_completer() - # TODO: init_io() needs to happen before init_traceback handlers - # because the traceback handlers hardcode the stdout/stderr streams. - # This logic in in debugger.Pdb and should eventually be changed. - self.init_io() - self.init_traceback_handlers(custom_exceptions) - self.init_prompts() - self.init_display_formatter() - self.init_display_pub() - self.init_data_pub() - self.init_displayhook() - self.init_magics() - self.init_alias() - self.init_logstart() - self.init_pdb() - self.init_extension_manager() - self.init_payload() - self.events.trigger('shell_initialized', self) - atexit.register(self.atexit_operations) - - # The trio runner is used for running Trio in the foreground thread. It - # is different from `_trio_runner(async_fn)` in `async_helpers.py` - # which calls `trio.run()` for every cell. This runner runs all cells - # inside a single Trio event loop. If used, it is set from - # `ipykernel.kernelapp`. - self.trio_runner = None - - def get_ipython(self): - """Return the currently running IPython instance.""" - return self - - #------------------------------------------------------------------------- - # Trait changed handlers - #------------------------------------------------------------------------- - @observe('ipython_dir') - def _ipython_dir_changed(self, change): - ensure_dir_exists(change['new']) - - def set_autoindent(self,value=None): - """Set the autoindent flag. - - If called with no arguments, it acts as a toggle.""" - if value is None: - self.autoindent = not self.autoindent - else: - self.autoindent = value - - def set_trio_runner(self, tr): - self.trio_runner = tr - - #------------------------------------------------------------------------- - # init_* methods called by __init__ - #------------------------------------------------------------------------- - - def init_ipython_dir(self, ipython_dir): - if ipython_dir is not None: - self.ipython_dir = ipython_dir - return - - self.ipython_dir = get_ipython_dir() - - def init_profile_dir(self, profile_dir): - if profile_dir is not None: - self.profile_dir = profile_dir - return - self.profile_dir = ProfileDir.create_profile_dir_by_name( - self.ipython_dir, "default" - ) - - def init_instance_attrs(self): - self.more = False - - # command compiler - self.compile = self.compiler_class() - - # Make an empty namespace, which extension writers can rely on both - # existing and NEVER being used by ipython itself. This gives them a - # convenient location for storing additional information and state - # their extensions may require, without fear of collisions with other - # ipython names that may develop later. - self.meta = Struct() - - # Temporary files used for various purposes. Deleted at exit. - # The files here are stored with Path from Pathlib - self.tempfiles = [] - self.tempdirs = [] - - # keep track of where we started running (mainly for crash post-mortem) - # This is not being used anywhere currently. - self.starting_dir = os.getcwd() - - # Indentation management - self.indent_current_nsp = 0 - - # Dict to track post-execution functions that have been registered - self._post_execute = {} - - def init_environment(self): - """Any changes we need to make to the user's environment.""" - pass - - def init_encoding(self): - # Get system encoding at startup time. Certain terminals (like Emacs - # under Win32 have it set to None, and we need to have a known valid - # encoding to use in the raw_input() method - try: - self.stdin_encoding = sys.stdin.encoding or 'ascii' - except AttributeError: - self.stdin_encoding = 'ascii' - - - @observe('colors') - def init_syntax_highlighting(self, changes=None): - # Python source parser/formatter for syntax highlighting - pyformat = PyColorize.Parser(style=self.colors, parent=self).format - self.pycolorize = lambda src: pyformat(src,'str') - - 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() - - self.dir_stack = [] - - def init_logger(self): - self.logger = Logger(self.home_dir, logfname='ipython_log.py', - logmode='rotate') - - def init_logstart(self): - """Initialize logging in case it was requested at the command line. - """ - if self.logappend: - self.magic('logstart %s append' % self.logappend) - elif self.logfile: - self.magic('logstart %s' % self.logfile) - elif self.logstart: - self.magic('logstart') - - - def init_builtins(self): - # A single, static flag that we set to True. Its presence indicates - # that an IPython shell has been created, and we make no attempts at - # removing on exit or representing the existence of more than one - # IPython at a time. - builtin_mod.__dict__['__IPYTHON__'] = True - builtin_mod.__dict__['display'] = display - - self.builtin_trap = BuiltinTrap(shell=self) - - @observe('colors') - def init_inspector(self, changes=None): - # Object inspector - self.inspector = oinspect.Inspector(oinspect.InspectColors, - PyColorize.ANSICodeColors, - self.colors, - self.object_info_string_level) - - def init_io(self): - # implemented in subclasses, TerminalInteractiveShell does call - # colorama.init(). - pass - - def init_prompts(self): - # Set system prompts, so that scripts can decide if they are running - # interactively. - sys.ps1 = 'In : ' - sys.ps2 = '...: ' - sys.ps3 = 'Out: ' - - def init_display_formatter(self): - self.display_formatter = DisplayFormatter(parent=self) - self.configurables.append(self.display_formatter) - - def init_display_pub(self): - self.display_pub = self.display_pub_class(parent=self, shell=self) - self.configurables.append(self.display_pub) - - def init_data_pub(self): - if not self.data_pub_class: - self.data_pub = None - return - self.data_pub = self.data_pub_class(parent=self) - self.configurables.append(self.data_pub) - - def init_displayhook(self): - # Initialize displayhook, set in/out prompts and printing system - self.displayhook = self.displayhook_class( - parent=self, - shell=self, - cache_size=self.cache_size, - ) - self.configurables.append(self.displayhook) - # This is a context manager that installs/revmoes the displayhook at - # the appropriate time. - self.display_trap = DisplayTrap(hook=self.displayhook) - - @staticmethod - def get_path_links(p: Path): - """Gets path links including all symlinks - - Examples - -------- - In [1]: from IPython.core.interactiveshell import InteractiveShell - - In [2]: import sys, pathlib - - In [3]: paths = InteractiveShell.get_path_links(pathlib.Path(sys.executable)) - - In [4]: len(paths) == len(set(paths)) - Out[4]: True - - In [5]: bool(paths) - Out[5]: True - """ - paths = [p] - while p.is_symlink(): - new_path = Path(os.readlink(p)) - if not new_path.is_absolute(): - new_path = p.parent / new_path - p = new_path - paths.append(p) - return paths - - def init_virtualenv(self): - """Add the current virtualenv to sys.path so the user can import modules from it. - This isn't perfect: it doesn't use the Python interpreter with which the - 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 - elif os.environ["VIRTUAL_ENV"] == "": - warn("Virtual env path set to '', please check if this is intended.") - return - - p = Path(sys.executable) - p_venv = Path(os.environ["VIRTUAL_ENV"]) - - # fallback 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. - # So we just check every item in the symlink tree (generally <= 3) - paths = self.get_path_links(p) - - # In Cygwin paths like "c:\..." and '\cygdrive\c\...' are possible - if p_venv.parts[1] == "cygdrive": - drive_name = p_venv.parts[2] - p_venv = (drive_name + ":/") / Path(*p_venv.parts[3:]) - - if any(p_venv == p.parents[1] for p in paths): - # Our exe is inside or has access to the virtualenv, don't need to do anything. - return - - if sys.platform == "win32": - virtual_env = str(Path(os.environ["VIRTUAL_ENV"], "Lib", "site-packages")) - else: - virtual_env_path = Path( - os.environ["VIRTUAL_ENV"], "lib", "python{}.{}", "site-packages" - ) - p_ver = sys.version_info[:2] - - # Predict version from py[thon]-x.x in the $VIRTUAL_ENV - re_m = re.search(r"\bpy(?:thon)?([23])\.(\d+)\b", os.environ["VIRTUAL_ENV"]) - if re_m: - predicted_path = Path(str(virtual_env_path).format(*re_m.groups())) - if predicted_path.exists(): - p_ver = re_m.groups() - - virtual_env = str(virtual_env_path).format(*p_ver) - - warn( - "Attempting to work in a virtualenv. If you encounter problems, " - "please install IPython inside the virtualenv." - ) - import site - sys.path.insert(0, virtual_env) - site.addsitedir(virtual_env) - - #------------------------------------------------------------------------- - # Things related to injections into the sys module - #------------------------------------------------------------------------- - - def save_sys_module_state(self): - """Save the state of hooks in the sys module. - - This has to be called after self.user_module is created. - """ - self._orig_sys_module_state = {'stdin': sys.stdin, - 'stdout': sys.stdout, - 'stderr': sys.stderr, - 'excepthook': sys.excepthook} - self._orig_sys_modules_main_name = self.user_module.__name__ - self._orig_sys_modules_main_mod = sys.modules.get(self.user_module.__name__) - - def restore_sys_module_state(self): - """Restore the state of the sys module.""" - try: - for k, v in self._orig_sys_module_state.items(): - setattr(sys, k, v) - except AttributeError: - pass - # Reset what what done in self.init_sys_modules - if self._orig_sys_modules_main_mod is not None: - sys.modules[self._orig_sys_modules_main_name] = self._orig_sys_modules_main_mod - - #------------------------------------------------------------------------- - # Things related to the banner - #------------------------------------------------------------------------- - - @property - def banner(self): - banner = self.banner1 - if self.profile and self.profile != 'default': - banner += '\nIPython profile: %s\n' % self.profile - if self.banner2: - banner += '\n' + self.banner2 - return banner - - def show_banner(self, banner=None): - if banner is None: - banner = self.banner - sys.stdout.write(banner) - - #------------------------------------------------------------------------- - # Things related to hooks - #------------------------------------------------------------------------- - - def init_hooks(self): - # hooks holds pointers used for user-side customizations - self.hooks = Struct() - - self.strdispatchers = {} - - # Set all default hooks, defined in the IPython.hooks module. - hooks = IPython.core.hooks - for hook_name in hooks.__all__: - # 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) - - 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): - """set_hook(name,hook) -> sets an internal IPython hook. - - IPython exposes some of its internal API as user-modifiable hooks. By - adding your function to one of these hooks, you can modify IPython's - behavior to call at runtime your own routines.""" - - # At some point in the future, this should validate the hook before it - # accepts it. Probably at least check that the hook takes the number - # of args it's supposed to. - - f = types.MethodType(hook,self) - - # check if the hook is for strdispatcher first - if str_key is not None: - sdp = self.strdispatchers.get(name, StrDispatch()) - sdp.add_s(str_key, f, priority ) - self.strdispatchers[name] = sdp - return - if re_key is not None: - sdp = self.strdispatchers.get(name, StrDispatch()) - sdp.add_re(re.compile(re_key), f, priority ) - self.strdispatchers[name] = sdp - return - - dp = getattr(self.hooks, name, None) - if name not in IPython.core.hooks.__all__: - print("Warning! Hook '%s' is not one of %s" % \ - (name, IPython.core.hooks.__all__ )) - - if name in IPython.core.hooks.deprecated: - alternative = IPython.core.hooks.deprecated[name] - raise ValueError( - "Hook {} has been deprecated since IPython 5.0. Use {} instead.".format( - name, alternative - ) - ) - - if not dp: - dp = IPython.core.hooks.CommandChainDispatcher() - - try: - dp.add(f,priority) - except AttributeError: - # it was not commandchain, plain old func - replace - dp = f - - setattr(self.hooks,name, dp) - - #------------------------------------------------------------------------- - # Things related to events - #------------------------------------------------------------------------- - - def init_events(self): - self.events = EventManager(self, available_events) - - self.events.register("pre_execute", self._clear_warning_registry) - - def register_post_execute(self, func): - """DEPRECATED: Use ip.events.register('post_run_cell', func) - - Register a function for calling after code execution. - """ - raise ValueError( - "ip.register_post_execute is deprecated since IPython 1.0, use " - "ip.events.register('post_run_cell', func) instead." - ) - - 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 - # warnings (see gh-6611 for details) - if "__warningregistry__" in self.user_global_ns: - del self.user_global_ns["__warningregistry__"] - - #------------------------------------------------------------------------- - # Things related to the "main" module - #------------------------------------------------------------------------- - - 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. - - This method keeps said reference in a private dict, keyed by the - absolute path of the script. This way, for multiple executions of the - same script we only keep one copy of the namespace (the last one), - thus preventing memory leaks from old references while allowing the - objects from the last execution to be accessible. - """ - filename = os.path.abspath(filename) - try: - main_mod = self._main_mod_cache[filename] - except KeyError: - main_mod = self._main_mod_cache[filename] = types.ModuleType( - modname, - doc="Module created for script run in IPython") - 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): - """Clear the cache of main modules. - - Mainly for use by utilities like %reset. - - Examples - -------- - In [15]: import IPython - - In [16]: m = _ip.new_main_mod(IPython.__file__, 'IPython') - - In [17]: len(_ip._main_mod_cache) > 0 - Out[17]: True - - In [18]: _ip.clear_main_mod_cache() - - In [19]: len(_ip._main_mod_cache) == 0 - Out[19]: True - """ - self._main_mod_cache.clear() - - #------------------------------------------------------------------------- - # Things related to debugging - #------------------------------------------------------------------------- - - def init_pdb(self): - # Set calling of pdb on exceptions - # self.call_pdb is a property - self.call_pdb = self.pdb - - def _get_call_pdb(self): - return self._call_pdb - - def _set_call_pdb(self,val): - - if val not in (0,1,False,True): - raise ValueError('new call_pdb value must be boolean') - - # store value in instance - self._call_pdb = val - - # notify the actual exception handlers - self.InteractiveTB.call_pdb = val - - call_pdb = property(_get_call_pdb,_set_call_pdb,None, - 'Control auto-activation of pdb at exceptions') - - def debugger(self,force=False): - """Call the pdb debugger. - - Keywords: - - - force(False): by default, this routine checks the instance call_pdb - flag and does not actually invoke the debugger if the flag is false. - The 'force' option forces the debugger to activate even if the flag - is false. - """ - - if not (force or self.call_pdb): - return - - if not hasattr(sys,'last_traceback'): - error('No traceback has been produced, nothing to debug.') - return - - self.InteractiveTB.debugger(force=True) - - #------------------------------------------------------------------------- - # Things related to IPython's various namespaces - #------------------------------------------------------------------------- - default_user_namespaces = True - - def init_create_namespaces(self, user_module=None, user_ns=None): - # Create the namespace where the user will operate. user_ns is - # normally the only one used, and it is passed to the exec calls as - # the locals argument. But we do carry a user_global_ns namespace - # given as the exec 'globals' argument, This is useful in embedding - # situations where the ipython shell opens in a context where the - # distinction between locals and globals is meaningful. For - # non-embedded contexts, it is just the same object as the user_ns dict. - - # FIXME. For some strange reason, __builtins__ is showing up at user - # level as a dict instead of a module. This is a manual fix, but I - # should really track down where the problem is coming from. Alex - # Schmolck reported this problem first. - - # A useful post by Alex Martelli on this topic: - # Re: inconsistent value from __builtins__ - # Von: Alex Martelli <aleaxit@yahoo.com> - # Datum: Freitag 01 Oktober 2004 04:45:34 nachmittags/abends - # Gruppen: comp.lang.python - - # Michael Hohn <hohn@hooknose.lbl.gov> wrote: - # > >>> print type(builtin_check.get_global_binding('__builtins__')) - # > <type 'dict'> - # > >>> print type(__builtins__) - # > <type 'module'> - # > Is this difference in return value intentional? - - # Well, it's documented that '__builtins__' can be either a dictionary - # or a module, and it's been that way for a long time. Whether it's - # intentional (or sensible), I don't know. In any case, the idea is - # that if you need to access the built-in namespace directly, you - # should start with "import __builtin__" (note, no 's') which will - # definitely give you a module. Yeah, it's somewhat confusing:-(. - - # These routines return a properly built module and dict as needed by - # the rest of the code, and can also be used by extension writers to - # generate properly initialized namespaces. - if (user_ns is not None) or (user_module is not None): - self.default_user_namespaces = False - self.user_module, self.user_ns = self.prepare_user_module(user_module, user_ns) - - # A record of hidden variables we have added to the user namespace, so - # we can list later only variables defined in actual interactive use. - self.user_ns_hidden = {} - - # Now that FakeModule produces a real module, we've run into a nasty - # problem: after script execution (via %run), the module where the user - # code ran is deleted. Now that this object is a true module (needed - # so doctest and other tools work correctly), the Python module - # teardown mechanism runs over it, and sets to None every variable - # present in that module. Top-level references to objects from the - # script survive, because the user_ns is updated with them. However, - # calling functions defined in the script that use other things from - # the script will fail, because the function's closure had references - # to the original objects, which are now all None. So we must protect - # these modules from deletion by keeping a cache. - # - # To avoid keeping stale modules around (we only need the one from the - # last run), we use a dict keyed with the full path to the script, so - # only the last version of the module is held in the cache. Note, - # however, that we must cache the module *namespace contents* (their - # __dict__). Because if we try to cache the actual modules, old ones - # (uncached) could be destroyed while still holding references (such as - # those held by GUI objects that tend to be long-lived)> - # - # The %reset command will flush this cache. See the cache_main_mod() - # and clear_main_mod_cache() methods for details on use. - - # This is the cache used for 'main' namespaces - self._main_mod_cache = {} - - # A table holding all the namespaces IPython deals with, so that - # introspection facilities can search easily. - self.ns_table = {'user_global':self.user_module.__dict__, - '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 - when embedding), user_ns is the local namespace, and user_module - provides the global namespace. - - Parameters - ---------- - user_module : module, optional - The current user module in which IPython is being run. If None, - a clean module will be created. - user_ns : dict, optional - A namespace in which to run interactive commands. - - Returns - ------- - A tuple of user_module and user_ns, each properly initialised. - """ - if user_module is None and user_ns is not None: - 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__ - - return user_module, user_ns - - def init_sys_modules(self): - # We need to insert into sys.modules something that looks like a - # module but which accesses the IPython namespace, for shelve and - # pickle to work interactively. Normally they rely on getting - # everything out of __main__, but for embedding purposes each IPython - # instance has its own private namespace, so we can't go shoving - # everything into __main__. - - # note, however, that we should only do this for non-embedded - # ipythons, which really mimic the __main__.__dict__ with their own - # namespace. Embedded instances, on the other hand, should not do - # this because they need to manage the user local/global namespaces - # only, but they live within a 'normal' __main__ (meaning, they - # shouldn't overtake the execution environment of the script they're - # embedded in). - - # This is overridden in the InteractiveShellEmbed subclass to a no-op. - main_name = self.user_module.__name__ - sys.modules[main_name] = self.user_module - - def init_user_ns(self): - """Initialize all user-visible namespaces to their minimum defaults. - - Certain history lists are also initialized here, as they effectively - act as user namespaces. - - Notes - ----- - All data structures here are only filled in, they are NOT reset by this - method. If they were not empty before, data will simply be added to - them. - """ - # This function works in two parts: first we put a few things in - # user_ns, and we sync that contents into user_ns_hidden so that these - # initial variables aren't shown by %who. After the sync, we add the - # rest of what we *do* want the user to see with %who even on a new - # session (probably nothing, so they really only see their own stuff) - - # The user dict must *always* have a __builtin__ reference to the - # Python standard __builtin__ namespace, which must be imported. - # This is so that certain operations in prompt evaluation can be - # reliably executed with builtins. Note that we can NOT use - # __builtins__ (note the 's'), because that can either be a dict or a - # module, and can even mutate at runtime, depending on the context - # (Python makes no guarantees on it). In contrast, __builtin__ is - # always a module object, though it must be explicitly imported. - - # For more details: - # http://mail.python.org/pipermail/python-dev/2001-April/014068.html - ns = {} - - # make global variables for user access to the histories - ns['_ih'] = self.history_manager.input_hist_parsed - ns['_oh'] = self.history_manager.output_hist - ns['_dh'] = self.history_manager.dir_hist - - # user aliases to input and output histories. These shouldn't show up - # in %who, as they can have very large reprs. - ns['In'] = self.history_manager.input_hist_parsed - ns['Out'] = self.history_manager.output_hist - - # Store myself as the public api!!! - ns['get_ipython'] = self.get_ipython - - ns['exit'] = self.exiter - ns['quit'] = self.exiter - - # Sync what we've added so far to user_ns_hidden so these aren't seen - # by %who - self.user_ns_hidden.update(ns) - - # Anything put into ns now would show up in %who. Think twice before - # putting anything here, as we really want %who to show the user their - # stuff, not our variables. - - # 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] + \ - [m.__dict__ for m in self._main_mod_cache.values()] - - def reset(self, new_session=True, aggressive=False): - """Clear all internal namespaces, and attempt to release references to - user objects. - - If new_session is True, a new history session will be opened. - """ - # Clear histories - self.history_manager.reset(new_session) - # Reset counter used to index all histories - if new_session: - self.execution_count = 1 - - # Reset last execution result - self.last_execution_succeeded = True - self.last_execution_result = None - - # Flush cached output items - if self.displayhook.do_full_cache: - self.displayhook.flush() - - # The main execution namespaces must be cleared very carefully, - # skipping the deletion of the builtin-related keys, because doing so - # would cause errors in many object's __del__ methods. - if self.user_ns is not self.user_global_ns: - self.user_ns.clear() - ns = self.user_global_ns - drop_keys = set(ns.keys()) - drop_keys.discard('__builtin__') - drop_keys.discard('__builtins__') - 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() - if aggressive and not hasattr(self, "_sys_modules_keys"): - print("Cannot restore sys.module, no snapshot") - elif aggressive: - print("culling sys module...") - current_keys = set(sys.modules.keys()) - for k in current_keys - self._sys_modules_keys: - if k.startswith("multiprocessing"): - continue - del sys.modules[k] - - # Restore the default and user aliases - self.alias_manager.clear_aliases() - self.alias_manager.init_aliases() - - # Now define aliases that only make sense on the terminal, because they - # need direct access to the console in a way that we can't emulate in - # GUI or web frontend - if os.name == 'posix': - for cmd in ('clear', 'more', 'less', 'man'): - if cmd not in self.magics_manager.magics['line']: - self.alias_manager.soft_define_alias(cmd, cmd) - - # Flush the private list of module references kept for script - # execution protection - self.clear_main_mod_cache() - - def del_var(self, varname, by_name=False): - """Delete a variable from the various namespaces, so that, as - far as possible, we're not keeping any hidden references to it. - - Parameters - ---------- - varname : str - The name of the variable to delete. - by_name : bool - If True, delete variables with the given name in each - namespace. If False (default), find the variable in the user - namespace, and delete references to it. - """ - if varname in ('__builtin__', '__builtins__'): - 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: - del ns[varname] - except KeyError: - pass - else: # Delete by object - try: - obj = self.user_ns[varname] - except KeyError as e: - raise NameError("name '%s' is not defined" % varname) from e - # Also check in output history - ns_refs.append(self.history_manager.output_hist) - for ns in ns_refs: - to_delete = [n for n, o in ns.items() if o is obj] - for name in to_delete: - del ns[name] - - # Ensure it is removed from the last execution result - if self.last_execution_result.result is obj: - self.last_execution_result = None - - # displayhook keeps extra references, but not in a dictionary - for name in ('_', '__', '___'): - if getattr(self.displayhook, name) is obj: - setattr(self.displayhook, name, None) - - def reset_selective(self, regex=None): - """Clear selective variables from internal namespaces based on a - specified regular expression. - - Parameters - ---------- - regex : string or compiled pattern, optional - A regular expression pattern that will be used in searching - variable names in the users namespaces. - """ - if regex is not None: - try: - m = re.compile(regex) - except TypeError as e: - raise TypeError('regex must be a string or compiled pattern') from e - # Search for keys in each namespace that match the given regex - # If a match is found, delete the key/value pair. - for ns in self.all_ns_refs: - for var in ns: - if m.search(var): - del ns[var] - - def push(self, variables, interactive=True): - """Inject a group of variables into the IPython user namespace. - - Parameters - ---------- - variables : dict, str or list/tuple of str - The variables to inject into the user's namespace. If a dict, a - simple update is done. If a str, the string is assumed to have - variable names separated by spaces. A list/tuple of str can also - be used to give the variable names. If just the variable names are - give (list/tuple/str) then the variable values looked up in the - callers frame. - interactive : bool - If True (default), the variables will be listed with the ``who`` - magic. - """ - vdict = None - - # We need a dict of name/value pairs to do namespace updates. - if isinstance(variables, dict): - vdict = variables - elif isinstance(variables, (str, list, tuple)): - if isinstance(variables, str): - vlist = variables.split() - else: - vlist = variables - vdict = {} - cf = sys._getframe(1) - for name in vlist: - try: - vdict[name] = eval(name, cf.f_globals, cf.f_locals) - except: - print('Could not get variable %s from %s' % - (name,cf.f_code.co_name)) - else: - raise ValueError('variables must be a dict/str/list/tuple') - - # Propagate variables to user namespace - self.user_ns.update(vdict) - - # And configure interactive visibility - user_ns_hidden = self.user_ns_hidden - if interactive: - for name in vdict: - user_ns_hidden.pop(name, None) - else: - user_ns_hidden.update(vdict) - - 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 - A dictionary mapping object names (as strings) to the objects. - """ - for name, obj in variables.items(): - if name in self.user_ns and self.user_ns[name] is obj: - del self.user_ns[name] - self.user_ns_hidden.pop(name, None) - - #------------------------------------------------------------------------- - # Things related to object introspection - #------------------------------------------------------------------------- - - def _ofind(self, oname, namespaces=None): - """Find an object in the available namespaces. - - self._ofind(oname) -> dict with keys: found,obj,ospace,ismagic - - Has special code to detect magic functions. - """ - oname = oname.strip() - if not oname.startswith(ESC_MAGIC) and \ - not oname.startswith(ESC_MAGIC2) and \ - not all(a.isidentifier() for a in oname.split(".")): - return {'found': False} - - if namespaces is None: - # Namespaces to search in: - # Put them in a list. The order is important so that we - # find things in the same order that Python finds them. - namespaces = [ ('Interactive', self.user_ns), - ('Interactive (global)', self.user_global_ns), - ('Python builtin', builtin_mod.__dict__), - ] - - ismagic = False - isalias = False - found = False - ospace = None - parent = None - obj = None - - - # Look for the given name by splitting it in parts. If the head is - # found, then we look for all the remaining parts as members, and only - # declare success if we can find them all. - oname_parts = oname.split('.') - oname_head, oname_rest = oname_parts[0],oname_parts[1:] - for nsname,ns in namespaces: - try: - obj = ns[oname_head] - except KeyError: - continue - else: - for idx, part in enumerate(oname_rest): - try: - parent = obj - # The last part is looked up in a special way to avoid - # descriptor invocation as it may raise or have side - # effects. - if idx == len(oname_rest) - 1: - obj = self._getattr_property(obj, part) - else: - obj = getattr(obj, part) - except: - # Blanket except b/c some badly implemented objects - # allow __getattr__ to raise exceptions other than - # AttributeError, which then crashes IPython. - break - else: - # If we finish the for loop (no break), we got all members - found = True - ospace = nsname - break # namespace loop - - # Try to see if it's magic - if not found: - obj = None - if oname.startswith(ESC_MAGIC2): - oname = oname.lstrip(ESC_MAGIC2) - obj = self.find_cell_magic(oname) - elif oname.startswith(ESC_MAGIC): - oname = oname.lstrip(ESC_MAGIC) - obj = self.find_line_magic(oname) - else: - # search without prefix, so run? will find %run? - obj = self.find_line_magic(oname) - if obj is None: - obj = self.find_cell_magic(oname) - if obj is not None: - found = True - ospace = 'IPython internal' - ismagic = True - isalias = isinstance(obj, Alias) - - # Last try: special-case some literals like '', [], {}, etc: - if not found and oname_head in ["''",'""','[]','{}','()']: - obj = eval(oname_head) - found = True - ospace = 'Interactive' - - return { - 'obj':obj, - 'found':found, - 'parent':parent, - 'ismagic':ismagic, - 'isalias':isalias, - 'namespace':ospace - } - - @staticmethod - def _getattr_property(obj, attrname): - """Property-aware getattr to use in object finding. - - If attrname represents a property, return it unevaluated (in case it has - side effects or raises an error. - - """ - if not isinstance(obj, type): - try: - # `getattr(type(obj), attrname)` is not guaranteed to return - # `obj`, but does so for property: - # - # property.__get__(self, None, cls) -> self - # - # The universal alternative is to traverse the mro manually - # searching for attrname in class dicts. - attr = getattr(type(obj), attrname) - except AttributeError: - pass - else: - # This relies on the fact that data descriptors (with both - # __get__ & __set__ magic methods) take precedence over - # instance-level attributes: - # - # class A(object): - # @property - # def foobar(self): return 123 - # a = A() - # a.__dict__['foobar'] = 345 - # a.foobar # == 123 - # - # So, a property may be returned right away. - if isinstance(attr, property): - return attr - - # Nothing helped, fall back. - return getattr(obj, attrname) - - def _object_find(self, oname, namespaces=None): - """Find an object and return a struct with info about it.""" - return Struct(self._ofind(oname, namespaces)) - - 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. - """ - info = self._object_find(oname, namespaces) - docformat = ( - sphinxify(self.object_inspect(oname)) 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 - 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, - ) - else: - pmethod(info.obj, oname) - else: - print('Object `%s` not found.' % oname) - return 'not found' # so callers can take other action - - def object_inspect(self, oname, detail_level=0): - """Get object info about oname""" - with self.builtin_trap: - info = self._object_find(oname) - if info.found: - return self.inspector.info(info.obj, oname, info=info, - detail_level=detail_level - ) - else: - return oinspect.object_info(name=oname, found=False) - - 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, omit_sections=()): - """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: - docformat = ( - sphinxify(self.object_inspect(oname)) - if self.sphinxify_docstring - else None - ) - return self.inspector._get_info( - info.obj, - oname, - info=info, - detail_level=detail_level, - formatter=docformat, - omit_sections=omit_sections, - ) - else: - raise KeyError(oname) - - #------------------------------------------------------------------------- - # Things related to history management - #------------------------------------------------------------------------- - - def init_history(self): - """Sets up the command history, and starts regular autosaves.""" - self.history_manager = HistoryManager(shell=self, parent=self) - self.configurables.append(self.history_manager) - - #------------------------------------------------------------------------- - # Things related to exception handling and tracebacks (not debugging) - #------------------------------------------------------------------------- - - debugger_cls = InterruptiblePdb - - def init_traceback_handlers(self, custom_exceptions): - # Syntax error handler. - self.SyntaxTB = ultratb.SyntaxTB(color_scheme='NoColor', parent=self) - - # The interactive one is initialized with an offset, meaning we always - # want to remove the topmost item in the traceback, which is our own - # internal code. Valid modes: ['Plain','Context','Verbose','Minimal'] - self.InteractiveTB = ultratb.AutoFormattedTB(mode = 'Plain', - color_scheme='NoColor', - tb_offset = 1, - check_cache=check_linecache_ipython, - debugger_cls=self.debugger_cls, parent=self) - - # 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 - # during the read-eval loop, it may get temporarily overwritten. - self.sys_excepthook = sys.excepthook - - # and add any custom exception handlers the user may have specified - self.set_custom_exc(*custom_exceptions) - - # Set the exception mode - self.InteractiveTB.set_mode(mode=self.xmode) - - def set_custom_exc(self, 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 - run_code() method). - - Parameters - ---------- - exc_tuple : tuple of exception classes - A *tuple* of exception classes, for which to call the defined - handler. It is very important that you use a tuple, and NOT A - LIST here, because of the way Python's except statement works. If - you only want to trap a single exception, use a singleton tuple:: - - exc_tuple == (MyCustomException,) - - handler : callable - handler must have the following signature:: - - def my_handler(self, etype, value, tb, tb_offset=None): - ... - return structured_traceback - - Your handler must return a structured traceback (a list of strings), - or None. - - This will be made into an instance method (via types.MethodType) - of IPython itself, and it will be called if any of the exceptions - listed in the exc_tuple are caught. If the handler is None, an - internal basic one is used, which just prints basic info. - - To protect IPython from crashes, if your handler ever raises an - exception or returns an invalid result, it will be immediately - disabled. - - Notes - ----- - WARNING: by putting in your own exception handler into IPython's main - execution loop, you run a very good chance of nasty crashes. This - facility should only be used if you really know what you are doing. - """ - - if not isinstance(exc_tuple, tuple): - raise TypeError("The custom exceptions must be given as a tuple.") - - 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) - - 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. - """ - msg = "CustomTB must return list of strings, not %r" % stb - if stb is None: - return [] - elif isinstance(stb, str): - return [stb] - elif not isinstance(stb, list): - raise TypeError(msg) - # it's a list - for line in stb: - # check every element - if not isinstance(line, str): - raise TypeError(msg) - return stb - - if handler is None: - wrapped = dummy_handler - 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. - """ - try: - stb = handler(self,etype,value,tb,tb_offset=tb_offset) - return validate_stb(stb) - except: - # clear custom handler immediately - self.set_custom_exc((), None) - 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:") - stb = self.InteractiveTB.structured_traceback( - (etype,value,tb), tb_offset=tb_offset - ) - return stb - - self.CustomTB = types.MethodType(wrapped,self) - self.custom_exceptions = exc_tuple - - def excepthook(self, etype, value, tb): - """One more defense for GUI apps that call sys.excepthook. - - GUI frameworks like wxPython trap exceptions and call - sys.excepthook themselves. I guess this is a feature that - enables them to keep running after exceptions that would - otherwise kill their mainloop. This is a bother for IPython - which expects to catch all of the program exceptions with a try: - except: statement. - - Normally, IPython sets sys.excepthook to a CrashHandler instance, so if - any app directly invokes sys.excepthook, it will look to the user like - IPython crashed. In order to work around this, we can disable the - CrashHandler and replace it with this excepthook instead, which prints a - regular traceback using our InteractiveTB. In this fashion, apps which - call sys.excepthook will generate a regular-looking exception from - IPython, and the CrashHandler will only be triggered by real IPython - crashes. - - This hook should be used sparingly, only in places which are not likely - to be true IPython errors. - """ - self.showtraceback((etype, value, tb), tb_offset=0) - - 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: - etype, value, tb = sys.exc_info() - else: - etype, value, tb = exc_tuple - - if etype is None: - 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 - # like pdb depend on their existence, so let's set them. If we - # find problems in the field, we'll need to revisit their use. - 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) - - def get_exception_only(self, exc_tuple=None): - """ - Return as a string (ending with a newline) the exception that - just occurred, without any traceback. - """ - etype, value, tb = self._get_exc_info(exc_tuple) - msg = traceback.format_exception_only(etype, value) - return ''.join(msg) - - def showtraceback(self, exc_tuple=None, filename=None, tb_offset=None, - exception_only=False, running_compiled_code=False): - """Display the exception that just occurred. - - If nothing is known about the exception, this is the method which - should be used throughout the code for presenting user tracebacks, - rather than directly invoking the InteractiveTB object. - - A specific showsyntaxerror() also exists, but this method can take - care of calling it if needed, so unless you are explicitly catching a - SyntaxError exception, don't try to analyze the stack manually and - simply call this method.""" - - try: - try: - etype, value, tb = self._get_exc_info(exc_tuple) - except ValueError: - 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. - self.showsyntaxerror(filename, running_compiled_code) - elif etype is UsageError: - self.show_usage_error(value) - else: - if exception_only: - stb = ['An exception has occurred, use %tb to see ' - 'the full traceback.\n'] - stb.extend(self.InteractiveTB.get_exception_only(etype, - value)) - else: - try: - # Exception classes can customise their traceback - we - # use this in IPython.parallel for exceptions occurring - # in the engines. This should return a list of strings. - if hasattr(value, "_render_traceback_"): - stb = value._render_traceback_() - else: - stb = self.InteractiveTB.structured_traceback( - etype, value, tb, tb_offset=tb_offset - ) - - except Exception: - print( - "Unexpected exception formatting exception. Falling back to standard exception" - ) - traceback.print_exc() - return None - - self._showtraceback(etype, value, stb) - if self.call_pdb: - # drop into debugger - self.debugger(force=True) - return - - # Actually show the traceback - self._showtraceback(etype, value, stb) - - except KeyboardInterrupt: - print('\n' + self.get_exception_only(), file=sys.stderr) - - def _showtraceback(self, etype, evalue, stb: str): - """Actually show a traceback. - - Subclasses may override this method to put the traceback on a different - place, like a side channel. - """ - val = self.InteractiveTB.stb2text(stb) - try: - print(val) - except UnicodeEncodeError: - print(val.encode("utf-8", "backslashreplace").decode()) - - def showsyntaxerror(self, filename=None, running_compiled_code=False): - """Display the syntax error that just occurred. - - This doesn't display a stack trace because there isn't one. - - If a filename is given, it is stuffed in the exception instead - of what was there before (because Python's parser always uses - "<string>" when reading from a string). - - If the syntax error occurred when running a compiled code (i.e. running_compile_code=True), - longer stack trace will be displayed. - """ - etype, value, last_traceback = self._get_exc_info() - - if filename and issubclass(etype, SyntaxError): - try: - value.filename = filename - except: - # Not the format we expect; leave it alone - pass - - # If the error occurred when executing compiled code, we should provide full stacktrace. - elist = traceback.extract_tb(last_traceback) if running_compiled_code else [] - stb = self.SyntaxTB.structured_traceback(etype, value, elist) - self._showtraceback(etype, value, stb) - - # This is overridden in TerminalInteractiveShell to show a message about - # the %paste magic. - def showindentationerror(self): - """Called by _run_cell when there's an IndentationError in code entered - at the prompt. - - This is overridden in TerminalInteractiveShell to show a message about - the %paste magic.""" - self.showsyntaxerror() - - @skip_doctest - def set_next_input(self, s, replace=False): - """ Sets the 'default' input string for the next command line. - - Example:: - - In [1]: _ip.set_next_input("Hello Word") - In [2]: Hello Word_ # cursor is here - """ - self.rl_next_input = s - - def _indent_current_str(self): - """return the current level of indentation as a string""" - return self.input_splitter.get_indent_spaces() * ' ' - - #------------------------------------------------------------------------- - # Things related to text completion - #------------------------------------------------------------------------- - - def init_completer(self): - """Initialize the completion machinery. - - This creates completion machinery that can be used by client code, - either interactively in-process (typically triggered by the readline - library), programmatically (such as in test suites) or out-of-process - (typically over the network by remote frontends). - """ - from IPython.core.completer import IPCompleter - from IPython.core.completerlib import ( - cd_completer, - magic_run_completer, - module_completer, - reset_completer, - ) - - self.Completer = IPCompleter(shell=self, - namespace=self.user_ns, - global_namespace=self.user_global_ns, - parent=self, - ) - self.configurables.append(self.Completer) - - # Add custom completers to the basic ones built into IPCompleter - sdisp = self.strdispatchers.get('complete_command', StrDispatch()) - self.strdispatchers['complete_command'] = sdisp - self.Completer.custom_completers = sdisp - - self.set_hook('complete_command', module_completer, str_key = 'import') - self.set_hook('complete_command', module_completer, str_key = 'from') - self.set_hook('complete_command', module_completer, str_key = '%aimport') - self.set_hook('complete_command', magic_run_completer, str_key = '%run') - self.set_hook('complete_command', cd_completer, str_key = '%cd') - self.set_hook('complete_command', reset_completer, str_key = '%reset') - - @skip_doctest - def complete(self, text, line=None, cursor_pos=None): - """Return the completed text and a list of completions. - - Parameters - ---------- - text : string - A string of text to be completed on. It can be given as empty and - instead a line/position pair are given. In this case, the - completer itself will split the line like readline does. - line : string, optional - The complete line that text is part of. - cursor_pos : int, optional - The position of the cursor on the input line. - - Returns - ------- - text : string - The actual text that was completed. - matches : list - A sorted list with all possible completions. - - Notes - ----- - The optional arguments allow the completion to take more context into - account, and are part of the low-level completion API. - - This is a wrapper around the completion mechanism, similar to what - readline does at the command line when the TAB key is hit. By - exposing it as a method, it can be used by other non-readline - environments (such as GUIs) for text completion. - - Examples - -------- - In [1]: x = 'hello' - - In [2]: _ip.complete('x.l') - Out[2]: ('x.l', ['x.ljust', 'x.lower', 'x.lstrip']) - """ - - # Inject names into __builtin__ so we can complete on the added names. - with self.builtin_trap: - return self.Completer.complete(text, line, cursor_pos) - - def set_custom_completer(self, completer, pos=0) -> None: - """Adds a new custom completer function. - - The position argument (defaults to 0) is the index in the completers - list where you want the completer to be inserted. - - `completer` should have the following signature:: - - def completion(self: Completer, text: string) -> List[str]: - raise NotImplementedError - - It will be bound to the current Completer instance and pass some text - and return a list with current completions to suggest to the user. - """ - - newcomp = types.MethodType(completer, self.Completer) - self.Completer.custom_matchers.insert(pos,newcomp) - - def set_completer_frame(self, frame=None): - """Set the frame of the completer.""" - if frame: - self.Completer.namespace = frame.f_locals - self.Completer.global_namespace = frame.f_globals - else: - self.Completer.namespace = self.user_ns - self.Completer.global_namespace = self.user_global_ns - - #------------------------------------------------------------------------- - # Things related to magics - #------------------------------------------------------------------------- - - def init_magics(self): - from IPython.core import magics as m - self.magics_manager = magic.MagicsManager(shell=self, - parent=self, - user_magics=m.UserMagics(self)) - self.configurables.append(self.magics_manager) - - # Expose as public API from the magics manager - self.register_magics = self.magics_manager.register - - self.register_magics(m.AutoMagics, m.BasicMagics, m.CodeMagics, - m.ConfigMagics, m.DisplayMagics, m.ExecutionMagics, - m.ExtensionMagics, m.HistoryMagics, m.LoggingMagics, - m.NamespaceMagics, m.OSMagics, m.PackagingMagics, - m.PylabMagics, m.ScriptMagics, - ) - self.register_magics(m.AsyncMagics) - - # Register Magic Aliases - mman = self.magics_manager - # FIXME: magic aliases should be defined by the Magics classes - # or in MagicsManager, not here - mman.register_alias('ed', 'edit') - mman.register_alias('hist', 'history') - mman.register_alias('rep', 'recall') - mman.register_alias('SVG', 'svg', 'cell') - mman.register_alias('HTML', 'html', 'cell') - mman.register_alias('file', 'writefile', 'cell') - - # FIXME: Move the color initialization to the DisplayHook, which - # should be split into a prompt manager and displayhook. We probably - # even need a centralize colors management object. - self.run_line_magic('colors', 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, magic_kind=magic_kind, magic_name=magic_name - ) - - def _find_with_lazy_load(self, /, type_, magic_name: str): - """ - Try to find a magic potentially lazy-loading it. - - Parameters - ---------- - - type_: "line"|"cell" - the type of magics we are trying to find/lazy load. - magic_name: str - The name of the magic we are trying to find/lazy load - - - Note that this may have any side effects - """ - finder = {"line": self.find_line_magic, "cell": self.find_cell_magic}[type_] - fn = finder(magic_name) - if fn is not None: - return fn - lazy = self.magics_manager.lazy_magics.get(magic_name) - if lazy is None: - return None - - self.run_line_magic("load_ext", lazy) - res = finder(magic_name) - return res - - def run_line_magic(self, magic_name: str, line, _stack_depth=1): - """Execute the given line magic. - - Parameters - ---------- - magic_name : str - Name of the desired magic function, without '%' prefix. - line : str - The rest of the input line as a single string. - _stack_depth : int - If run_line_magic() is called from magic() then _stack_depth=2. - This is added to ensure backward compatibility for use of 'get_ipython().magic()' - """ - fn = self._find_with_lazy_load("line", magic_name) - if fn is None: - lazy = self.magics_manager.lazy_magics.get(magic_name) - if lazy: - self.run_line_magic("load_ext", lazy) - fn = self.find_line_magic(magic_name) - if fn is None: - cm = self.find_cell_magic(magic_name) - etpl = "Line magic function `%%%s` not found%s." - extra = '' if cm is None else (' (But cell magic `%%%%%s` exists, ' - 'did you mean that instead?)' % magic_name ) - raise UsageError(etpl % (magic_name, extra)) - else: - # Note: this is the distance in the stack to the user's frame. - # This will need to be updated if the internal calling logic gets - # refactored, or else we'll be expanding the wrong variables. - - # Determine stack_depth depending on where run_line_magic() has been called - stack_depth = _stack_depth - if getattr(fn, magic.MAGIC_NO_VAR_EXPAND_ATTR, False): - # magic has opted out of var_expand - magic_arg_s = line - else: - magic_arg_s = self.var_expand(line, stack_depth) - # Put magic args in a list so we can call with f(*a) syntax - args = [magic_arg_s] - kwargs = {} - # Grab local namespace if we need it: - if getattr(fn, "needs_local_scope", False): - kwargs['local_ns'] = self.get_local_scope(stack_depth) - with self.builtin_trap: - result = fn(*args, **kwargs) - return result - - def get_local_scope(self, stack_depth): - """Get local scope at given stack depth. - - Parameters - ---------- - stack_depth : int - Depth relative to calling frame - """ - return sys._getframe(stack_depth + 1).f_locals - - def run_cell_magic(self, magic_name, line, cell): - """Execute the given cell magic. - - Parameters - ---------- - magic_name : str - Name of the desired magic function, without '%' prefix. - line : str - The rest of the first input line as a single string. - cell : str - The body of the cell as a (possibly multiline) string. - """ - fn = self._find_with_lazy_load("cell", magic_name) - if fn is None: - lm = self.find_line_magic(magic_name) - etpl = "Cell magic `%%{0}` not found{1}." - extra = '' if lm is None else (' (But line magic `%{0}` exists, ' - 'did you mean that instead?)'.format(magic_name)) - raise UsageError(etpl.format(magic_name, extra)) - elif cell == '': - message = '%%{0} is a cell magic, but the cell body is empty.'.format(magic_name) - if self.find_line_magic(magic_name) is not None: - message += ' Did you mean the line magic %{0} (single %)?'.format(magic_name) - raise UsageError(message) - else: - # Note: this is the distance in the stack to the user's frame. - # This will need to be updated if the internal calling logic gets - # refactored, or else we'll be expanding the wrong variables. - stack_depth = 2 - if getattr(fn, magic.MAGIC_NO_VAR_EXPAND_ATTR, False): - # magic has opted out of var_expand - magic_arg_s = line - else: - magic_arg_s = self.var_expand(line, stack_depth) - kwargs = {} - if getattr(fn, "needs_local_scope", False): - kwargs['local_ns'] = self.user_ns - - with self.builtin_trap: - args = (magic_arg_s, cell) - result = fn(*args, **kwargs) - return result - - def find_line_magic(self, magic_name): - """Find and return a line magic by name. - - Returns None if the magic isn't found.""" - return self.magics_manager.magics['line'].get(magic_name) - - def find_cell_magic(self, magic_name): - """Find and return a cell magic by name. - - Returns None if the magic isn't found.""" - return self.magics_manager.magics['cell'].get(magic_name) - - def find_magic(self, magic_name, magic_kind='line'): - """Find and return a magic of the given type by name. - - Returns None if the magic isn't found.""" - return self.magics_manager.magics[magic_kind].get(magic_name) - - def magic(self, arg_s): - """ - DEPRECATED - - Deprecated since IPython 0.13 (warning added in - 8.1), use run_line_magic(magic_name, parameter_s). - - Call a magic function by name. - - Input: a string containing the name of the magic function to call and - any additional arguments to be passed to the magic. - - magic('name -opt foo bar') is equivalent to typing at the ipython - prompt: - - In[1]: %name -opt foo bar - - To call a magic without arguments, simply use magic('name'). - - This provides a proper Python function to call IPython's magics in any - valid Python code you can type at the interpreter, including loops and - compound statements. - """ - warnings.warn( - "`magic(...)` is deprecated since IPython 0.13 (warning added in " - "8.1), use run_line_magic(magic_name, parameter_s).", - DeprecationWarning, - stacklevel=2, - ) - # TODO: should we issue a loud deprecation warning here? - magic_name, _, magic_arg_s = arg_s.partition(' ') - magic_name = magic_name.lstrip(prefilter.ESC_MAGIC) - return self.run_line_magic(magic_name, magic_arg_s, _stack_depth=2) - - #------------------------------------------------------------------------- - # Things related to macros - #------------------------------------------------------------------------- - - def define_macro(self, name, themacro): - """Define a new macro - - Parameters - ---------- - name : str - The name of the macro. - themacro : str or Macro - The action to do upon invoking the macro. If a string, a new - Macro object is created by passing the string to it. - """ - - from IPython.core import macro - - if isinstance(themacro, str): - themacro = macro.Macro(themacro) - if not isinstance(themacro, macro.Macro): - raise ValueError('A macro must be a string or a Macro instance.') - self.user_ns[name] = themacro - - #------------------------------------------------------------------------- - # Things related to the running of system commands - #------------------------------------------------------------------------- - - def system_piped(self, cmd): - """Call the given cmd in a subprocess, piping stdout/err - - Parameters - ---------- - cmd : str - Command to execute (can not end in '&', as background processes are - not supported. Should not be a command that expects input - other than simple text. - """ - if cmd.rstrip().endswith('&'): - # this is *far* from a rigorous test - # We do not support backgrounding processes because we either use - # pexpect or pipes to read from. Users can always just call - # os.system() or use ip.system=ip.system_raw - # if they really want a background process. - raise OSError("Background processes not supported.") - - # 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. - self.user_ns['_exit_code'] = system(self.var_expand(cmd, depth=1)) - - def system_raw(self, cmd): - """Call the given cmd in a subprocess using os.system on Windows or - subprocess.call using the system shell on other platforms. - - Parameters - ---------- - cmd : str - Command to execute. - """ - cmd = self.var_expand(cmd, depth=1) - # warn if there is an IPython magic alternative. - main_cmd = cmd.split()[0] - has_magic_alternatives = ("pip", "conda", "cd") - - if main_cmd in has_magic_alternatives: - warnings.warn( - ( - "You executed the system command !{0} which may not work " - "as expected. Try the IPython magic %{0} instead." - ).format(main_cmd) - ) - - # protect os.system from UNC paths on Windows, which it can't handle: - if sys.platform == 'win32': - from IPython.utils._process_win32 import AvoidUNCPath - with AvoidUNCPath() as path: - if path is not None: - cmd = '"pushd %s &&"%s' % (path, cmd) - try: - ec = os.system(cmd) - except KeyboardInterrupt: - print('\n' + self.get_exception_only(), file=sys.stderr) - ec = -2 - else: - # For posix the result of the subprocess.call() below is an exit - # code, which by convention is zero for success, positive for - # program failure. Exit codes above 128 are reserved for signals, - # and the formula for converting a signal to an exit code is usually - # signal_number+128. To more easily differentiate between exit - # codes and signals, ipython uses negative numbers. For instance - # since control-c is signal 2 but exit code 130, ipython's - # _exit_code variable will read -2. Note that some shells like - # csh and fish don't follow sh/bash conventions for exit codes. - executable = os.environ.get('SHELL', None) - try: - # Use env shell instead of default /bin/sh - 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) - 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 - # of _exit_code: for control-c, _exit_code == -signal.SIGNIT, - # but raising SystemExit(_exit_code) will give status 254! - self.user_ns['_exit_code'] = ec - - # use piped system by default, because it is better behaved - system = system_piped - - def getoutput(self, cmd, split=True, depth=0): - """Get output (possibly including stderr) from a subprocess. - - Parameters - ---------- - cmd : str - Command to execute (can not end in '&', as background processes are - not supported. - split : bool, optional - If True, split the output into an IPython SList. Otherwise, an - IPython LSString is returned. These are objects similar to normal - lists and strings, with a few convenience attributes for easier - manipulation of line-based output. You can use '?' on them for - details. - depth : int, optional - How many frames above the caller are the local variables which should - be expanded in the command string? The default (0) assumes that the - expansion variables are in the stack frame calling this function. - """ - if cmd.rstrip().endswith('&'): - # this is *far* from a rigorous test - raise OSError("Background processes not supported.") - out = getoutput(self.var_expand(cmd, depth=depth+1)) - if split: - out = SList(out.splitlines()) - else: - out = LSString(out) - return out - - #------------------------------------------------------------------------- - # Things related to aliases - #------------------------------------------------------------------------- - - def init_alias(self): - self.alias_manager = AliasManager(shell=self, parent=self) - self.configurables.append(self.alias_manager) - - #------------------------------------------------------------------------- - # Things related to extensions - #------------------------------------------------------------------------- - - def init_extension_manager(self): - self.extension_manager = ExtensionManager(shell=self, parent=self) - self.configurables.append(self.extension_manager) - - #------------------------------------------------------------------------- - # Things related to payloads - #------------------------------------------------------------------------- - - def init_payload(self): - self.payload_manager = PayloadManager(parent=self) - self.configurables.append(self.payload_manager) - - #------------------------------------------------------------------------- - # Things related to the prefilter - #------------------------------------------------------------------------- - - def init_prefilter(self): - self.prefilter_manager = PrefilterManager(shell=self, parent=self) - self.configurables.append(self.prefilter_manager) - # Ultimately this will be refactored in the new interpreter code, but - # for now, we should expose the main prefilter method (there's legacy - # code out there that may rely on this). - self.prefilter = self.prefilter_manager.prefilter_lines - - def auto_rewrite_input(self, cmd): - """Print to the screen the rewritten form of the user's command. - - This shows visual feedback by rewriting input lines that cause - automatic calling to kick in, like:: - - /f x - - into:: - - ------> f(x) - - after the user's input prompt. This helps the user understand that the - input line was transformed automatically by IPython. - """ - if not self.show_rewritten_input: - return - - # This is overridden in TerminalInteractiveShell to use fancy prompts - print("------> " + cmd) - - #------------------------------------------------------------------------- - # Things related to extracting values/expressions from kernel and user_ns - #------------------------------------------------------------------------- - - 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 = { - "status": "error", - "traceback": stb, - "ename": etype.__name__, - "evalue": py3compat.safe_unicode(evalue), - } - - 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', - 'data' : data, - 'metadata' : md, - } - return value - - def user_expressions(self, expressions): - """Evaluate a dict of expressions in the user's namespace. - - Parameters - ---------- - expressions : dict - A dict with string keys and string values. The expression values - should be valid Python expressions, each of which will be evaluated - in the user namespace. - - Returns - ------- - A dict, keyed like the input expressions dict, with the rich mime-typed - display_data of each value. - """ - out = {} - user_ns = self.user_ns - global_ns = self.user_global_ns - - for key, expr in expressions.items(): - try: - value = self._format_user_obj(eval(expr, global_ns, user_ns)) - except: - value = self._user_obj_error() - out[key] = value - return out - - #------------------------------------------------------------------------- - # Things related to the running of code - #------------------------------------------------------------------------- - - def ex(self, cmd): - """Execute a normal python statement in user namespace.""" - with self.builtin_trap: - exec(cmd, self.user_global_ns, self.user_ns) - - def ev(self, expr): - """Evaluate python expression expr in user namespace. - - Returns the result of evaluation - """ - with self.builtin_trap: - return eval(expr, self.user_global_ns, self.user_ns) - - def safe_execfile(self, fname, *where, exit_ignore=False, raise_exceptions=False, shell_futures=False): - """A safe version of the builtin execfile(). - - This version will never throw an exception, but instead print - helpful error messages to the screen. This only works on pure - Python files with the .py extension. - - Parameters - ---------- - fname : string - The name of the file to be executed. - *where : tuple - One or two namespaces, passed to execfile() as (globals,locals). - If only one is given, it is passed as both. - exit_ignore : bool (False) - If True, then silence SystemExit for non-zero status (it is always - silenced for zero status, as it is so common). - raise_exceptions : bool (False) - If True raise exceptions everywhere. Meant for testing. - shell_futures : bool (False) - If True, the code will share future statements with the interactive - shell. It will both be affected by previous __future__ imports, and - any __future__ imports in the code will affect the shell. If False, - __future__ imports are not shared in either direction. - - """ - fname = Path(fname).expanduser().resolve() - - # Make sure we can open the file - try: - with fname.open("rb"): - pass - except: - warn('Could not open file <%s> for safe execution.' % fname) - return - - # Find things also in current directory. This is needed to mimic the - # behavior of running a script from the system command line, where - # Python inserts the script's directory into sys.path - dname = str(fname.parent) - - with prepended_to_syspath(dname), self.builtin_trap: - try: - glob, loc = (where + (None, ))[:2] - py3compat.execfile( - fname, glob, loc, - self.compile if shell_futures else None) - except SystemExit as status: - # If the call was made with 0 or None exit status (sys.exit(0) - # or sys.exit() ), don't bother showing a traceback, as both of - # these are considered normal by the OS: - # > python -c'import sys;sys.exit(0)'; echo $? - # 0 - # > python -c'import sys;sys.exit()'; echo $? - # 0 - # For other exit status, we show the exception unless - # explicitly silenced, but only in short form. - if status.code: - if raise_exceptions: - raise - if not exit_ignore: - self.showtraceback(exception_only=True) - except: - if raise_exceptions: - raise - # tb offset is 2 because we wrap execfile - self.showtraceback(tb_offset=2) - - def safe_execfile_ipy(self, fname, shell_futures=False, raise_exceptions=False): - """Like safe_execfile, but for .ipy or .ipynb files with IPython syntax. - - Parameters - ---------- - fname : str - The name of the file to execute. The filename must have a - .ipy or .ipynb extension. - shell_futures : bool (False) - If True, the code will share future statements with the interactive - shell. It will both be affected by previous __future__ imports, and - any __future__ imports in the code will affect the shell. If False, - __future__ imports are not shared in either direction. - raise_exceptions : bool (False) - If True raise exceptions everywhere. Meant for testing. - """ - fname = Path(fname).expanduser().resolve() - - # Make sure we can open the file - try: - with fname.open("rb"): - pass - except: - warn('Could not open file <%s> for safe execution.' % fname) - return - - # Find things also in current directory. This is needed to mimic the - # behavior of running a script from the system command line, where - # Python inserts the script's directory into sys.path - dname = str(fname.parent) - - def get_cells(): - """generator for sequence of code blocks to run""" - if fname.suffix == ".ipynb": - from nbformat import read - nb = read(fname, as_version=4) - if not nb.cells: - return - for cell in nb.cells: - if cell.cell_type == 'code': - yield cell.source - else: - yield fname.read_text(encoding="utf-8") - - with prepended_to_syspath(dname): - try: - for cell in get_cells(): - result = self.run_cell(cell, silent=True, shell_futures=shell_futures) - if raise_exceptions: - result.raise_error() - elif not result.success: - break - except: - if raise_exceptions: - raise - self.showtraceback() - warn('Unknown failure executing file: <%s>' % fname) - - def safe_run_module(self, mod_name, where): - """A safe version of runpy.run_module(). - - This version will never throw an exception, but instead print - helpful error messages to the screen. - - `SystemExit` exceptions with status code 0 or None are ignored. - - Parameters - ---------- - mod_name : string - The name of the module to be executed. - where : dict - The globals namespace. - """ - try: - try: - where.update( - runpy.run_module(str(mod_name), run_name="__main__", - alter_sys=True) - ) - except SystemExit as status: - if status.code: - raise - except: - self.showtraceback() - warn('Unknown failure executing module: <%s>' % mod_name) - - def run_cell( - self, - raw_cell, - store_history=False, - silent=False, - shell_futures=True, - cell_id=None, - ): - """Run a complete IPython cell. - - Parameters - ---------- - raw_cell : str - The code (including IPython code such as %magic functions) to run. - store_history : bool - If True, the raw and translated cell will be stored in IPython's - history. For user code calling back into IPython's machinery, this - should be set to False. - silent : bool - If True, avoid side-effects, such as implicit displayhooks and - and logging. silent=True forces store_history=False. - shell_futures : bool - If True, the code will share future statements with the interactive - shell. It will both be affected by previous __future__ imports, and - any __future__ imports in the code will affect the shell. If False, - __future__ imports are not shared in either direction. - - Returns - ------- - result : :class:`ExecutionResult` - """ - result = None - try: - result = self._run_cell( - raw_cell, store_history, silent, shell_futures, cell_id - ) - finally: - self.events.trigger('post_execute') - if not silent: - self.events.trigger('post_run_cell', result) - return result - - def _run_cell( - self, - raw_cell: str, - store_history: bool, - silent: bool, - shell_futures: bool, - cell_id: str, - ) -> ExecutionResult: - """Internal method to run a complete IPython cell.""" - - # we need to avoid calling self.transform_cell multiple time on the same thing - # so we need to store some results: - preprocessing_exc_tuple = None - try: - transformed_cell = self.transform_cell(raw_cell) - except Exception: - transformed_cell = raw_cell - preprocessing_exc_tuple = sys.exc_info() - - assert transformed_cell is not None - coro = self.run_cell_async( - raw_cell, - store_history=store_history, - silent=silent, - shell_futures=shell_futures, - transformed_cell=transformed_cell, - preprocessing_exc_tuple=preprocessing_exc_tuple, - cell_id=cell_id, - ) - - # run_cell_async is async, but may not actually need an eventloop. - # when this is the case, we want to run it using the pseudo_sync_runner - # so that code can invoke eventloops (for example via the %run , and - # `%paste` magic. - if self.trio_runner: - runner = self.trio_runner - elif self.should_run_async( - raw_cell, - transformed_cell=transformed_cell, - preprocessing_exc_tuple=preprocessing_exc_tuple, - ): - runner = self.loop_runner - else: - runner = _pseudo_sync_runner - - try: - return runner(coro) - except BaseException as e: - info = ExecutionInfo( - raw_cell, store_history, silent, shell_futures, cell_id - ) - result = ExecutionResult(info) - result.error_in_exec = e - self.showtraceback(running_compiled_code=True) - return result - - def should_run_async( - self, raw_cell: str, *, transformed_cell=None, preprocessing_exc_tuple=None - ) -> bool: - """Return whether a cell should be run asynchronously via a coroutine runner - - Parameters - ---------- - raw_cell : str - The code to be executed - - Returns - ------- - result: bool - Whether the code needs to be run with a coroutine runner or not - .. versionadded:: 7.0 - """ - if not self.autoawait: - return False - if preprocessing_exc_tuple is not None: - return False - assert preprocessing_exc_tuple is None - if transformed_cell is None: - warnings.warn( - "`should_run_async` will not call `transform_cell`" - " automatically in the future. Please pass the result to" - " `transformed_cell` argument and any exception that happen" - " during the" - "transform in `preprocessing_exc_tuple` in" - " IPython 7.17 and above.", - DeprecationWarning, - stacklevel=2, - ) - try: - cell = self.transform_cell(raw_cell) - except Exception: - # any exception during transform will be raised - # prior to execution - return False - else: - cell = transformed_cell - return _should_be_async(cell) - - async def run_cell_async( - self, - raw_cell: str, - store_history=False, - silent=False, - shell_futures=True, - *, - transformed_cell: Optional[str] = None, - preprocessing_exc_tuple: Optional[Any] = None, - cell_id=None, - ) -> ExecutionResult: - """Run a complete IPython cell asynchronously. - - Parameters - ---------- - raw_cell : str - The code (including IPython code such as %magic functions) to run. - store_history : bool - If True, the raw and translated cell will be stored in IPython's - history. For user code calling back into IPython's machinery, this - should be set to False. - silent : bool - If True, avoid side-effects, such as implicit displayhooks and - and logging. silent=True forces store_history=False. - shell_futures : bool - If True, the code will share future statements with the interactive - shell. It will both be affected by previous __future__ imports, and - any __future__ imports in the code will affect the shell. If False, - __future__ imports are not shared in either direction. - transformed_cell: str - cell that was passed through transformers - preprocessing_exc_tuple: - trace if the transformation failed. - - Returns - ------- - result : :class:`ExecutionResult` - - .. versionadded:: 7.0 - """ - info = ExecutionInfo(raw_cell, store_history, silent, shell_futures, cell_id) - result = ExecutionResult(info) - - if (not raw_cell) or raw_cell.isspace(): - self.last_execution_succeeded = True - self.last_execution_result = result - return result - - if silent: - store_history = False - - if store_history: - result.execution_count = self.execution_count - - def error_before_exec(value): - if store_history: - self.execution_count += 1 - result.error_before_exec = value - self.last_execution_succeeded = False - self.last_execution_result = result - return result - - self.events.trigger('pre_execute') - if not silent: - self.events.trigger('pre_run_cell', info) - - if transformed_cell is None: - warnings.warn( - "`run_cell_async` will not call `transform_cell`" - " automatically in the future. Please pass the result to" - " `transformed_cell` argument and any exception that happen" - " during the" - "transform in `preprocessing_exc_tuple` in" - " IPython 7.17 and above.", - DeprecationWarning, - stacklevel=2, - ) - # If any of our input transformation (input_transformer_manager or - # prefilter_manager) raises an exception, we store it in this variable - # so that we can display the error after logging the input and storing - # it in the history. - try: - cell = self.transform_cell(raw_cell) - except Exception: - preprocessing_exc_tuple = sys.exc_info() - cell = raw_cell # cell has to exist so it can be stored/logged - else: - preprocessing_exc_tuple = None - else: - if preprocessing_exc_tuple is None: - cell = transformed_cell - else: - cell = raw_cell - - # Store raw and processed history - if store_history and raw_cell.strip(" %") != "paste": - self.history_manager.store_inputs(self.execution_count, cell, raw_cell) - if not silent: - self.logger.log(cell, raw_cell) - - # Display the exception if input processing failed. - if preprocessing_exc_tuple is not None: - self.showtraceback(preprocessing_exc_tuple) - if store_history: - self.execution_count += 1 - return error_before_exec(preprocessing_exc_tuple[1]) - - # Our own compiler remembers the __future__ environment. If we want to - # run code with a separate __future__ environment, use the default - # compiler - compiler = self.compile if shell_futures else self.compiler_class() - - _run_async = False - - with self.builtin_trap: - cell_name = compiler.cache(cell, self.execution_count, raw_code=raw_cell) - - with self.display_trap: - # 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 IndentationError as e: - self.showindentationerror() - return error_before_exec(e) - except (OverflowError, SyntaxError, ValueError, TypeError, - MemoryError) as e: - self.showsyntaxerror() - return error_before_exec(e) - - # Apply AST transformations - try: - code_ast = self.transform_ast(code_ast) - except InputRejected as e: - self.showtraceback() - return error_before_exec(e) - - # Give the displayhook a reference to our ExecutionResult so it - # can fill in the output value. - self.displayhook.exec_result = result - - # Execute the user code - interactivity = "none" if silent else self.ast_node_interactivity - - has_raised = await 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_result = result - - # Reset this so later displayed values do not modify the - # ExecutionResult - self.displayhook.exec_result = None - - if store_history: - # Write output to the database. Does nothing unless - # history output logging is enabled. - self.history_manager.store_output(self.execution_count) - # Each cell is a *single* input, regardless of how many lines it has - self.execution_count += 1 - - return result - - def transform_cell(self, raw_cell): - """Transform an input cell before parsing it. - - Static transformations, implemented in IPython.core.inputtransformer2, - deal with things like ``%magic`` and ``!system`` commands. - These run on all input. - Dynamic transformations, for things like unescaped magics and the exit - autocall, depend on the state of the interpreter. - These only apply to single line inputs. - - These string-based transformations are followed by AST transformations; - see :meth:`transform_ast`. - """ - # Static input transformations - cell = self.input_transformer_manager.transform_cell(raw_cell) - - if len(cell.splitlines()) == 1: - # Dynamic transformations - only applied for single line commands - with self.builtin_trap: - # use prefilter_lines to handle trailing newlines - # restore trailing newline for ast.parse - cell = self.prefilter_manager.prefilter_lines(cell) + '\n' - - lines = cell.splitlines(keepends=True) - for transform in self.input_transformers_post: - lines = transform(lines) - cell = ''.join(lines) - - return cell - - 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 - may also modify the passed object, so don't rely on references to the - original AST. - """ - for transformer in self.ast_transformers: - try: - node = transformer.visit(node) - except InputRejected: - # User-supplied AST transformers can reject an input by raising - # an InputRejected. Short-circuit in this case so that we - # don't unregister the transform. - raise - 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 _update_code_co_name(self, code): - """Python 3.10 changed the behaviour so that whenever a code object - is assembled in the compile(ast) the co_firstlineno would be == 1. - - This makes pydevd/debugpy think that all cells invoked are the same - since it caches information based on (co_firstlineno, co_name, co_filename). - - Given that, this function changes the code 'co_name' to be unique - based on the first real lineno of the code (which also has a nice - side effect of customizing the name so that it's not always <module>). - - See: https://github.com/ipython/ipykernel/issues/841 - """ - if not hasattr(code, "replace"): - # It may not be available on older versions of Python (only - # available for 3.8 onwards). - return code - try: - first_real_line = next(dis.findlinestarts(code))[1] - except StopIteration: - return code - return code.replace(co_name="<cell line: %s>" % (first_real_line,)) - - async def run_ast_nodes( - self, - nodelist: ListType[stmt], - cell_name: str, - interactivity="last_expr", - compiler=compile, - result=None, - ): - """Run a sequence of AST nodes. The execution mode depends on the - interactivity parameter. - - Parameters - ---------- - nodelist : list - A sequence of AST nodes to run. - cell_name : str - Will be passed to the compiler as the filename of the cell. Typically - the value returned by ip.compile.cache(cell). - interactivity : str - 'all', 'last', 'last_expr' , 'last_expr_or_assign' or 'none', - specifying which nodes should be run interactively (displaying output - from expressions). 'last_expr' will run the last node interactively - only if it is an expression (i.e. expressions in loops or other blocks - are not displayed) 'last_expr_or_assign' will run the last expression - or the last assignment. Other values for this parameter will raise a - ValueError. - - compiler : callable - A function with the same interface as the built-in compile(), to turn - the AST nodes into code objects. Default is the built-in compile(). - result : ExecutionResult, optional - An object to store exceptions that occur during execution. - - Returns - ------- - True if an exception occurred while running code, False if it finished - running. - """ - if not nodelist: - return - - - if interactivity == 'last_expr_or_assign': - if isinstance(nodelist[-1], _assign_nodes): - asg = nodelist[-1] - if isinstance(asg, ast.Assign) and len(asg.targets) == 1: - target = asg.targets[0] - elif isinstance(asg, _single_targets_nodes): - target = asg.target - else: - target = None - if isinstance(target, ast.Name): - nnode = ast.Expr(ast.Name(target.id, ast.Load())) - ast.fix_missing_locations(nnode) - nodelist.append(nnode) - interactivity = 'last_expr' - - _async = False - if interactivity == 'last_expr': - if isinstance(nodelist[-1], ast.Expr): - interactivity = "last" - else: - interactivity = "none" - - if interactivity == 'none': - to_run_exec, to_run_interactive = nodelist, [] - elif interactivity == 'last': - to_run_exec, to_run_interactive = nodelist[:-1], nodelist[-1:] - elif interactivity == 'all': - to_run_exec, to_run_interactive = [], nodelist - else: - raise ValueError("Interactivity was %r" % interactivity) - - try: - - def compare(code): - is_async = inspect.CO_COROUTINE & code.co_flags == inspect.CO_COROUTINE - return is_async - - # refactor that to just change the mod constructor. - to_run = [] - for node in to_run_exec: - to_run.append((node, "exec")) - - for node in to_run_interactive: - to_run.append((node, "single")) - - for node, mode in to_run: - if mode == "exec": - mod = Module([node], []) - elif mode == "single": - mod = ast.Interactive([node]) - with compiler.extra_flags( - getattr(ast, "PyCF_ALLOW_TOP_LEVEL_AWAIT", 0x0) - if self.autoawait - else 0x0 - ): - code = compiler(mod, cell_name, mode) - code = self._update_code_co_name(code) - asy = compare(code) - if await self.run_code(code, result, async_=asy): - return True - - # Flush softspace - if softspace(sys.stdout, 0): - print() - - except: - # It's possible to have exceptions raised here, typically by - # compilation of odd code (such as a naked 'return' outside a - # function) that did parse but isn't valid. Typically the exception - # is a SyntaxError, but it's safest just to catch anything and show - # the user a traceback. - - # We do only one try/except outside the loop to minimize the impact - # on runtime, and also because if any node in the node list is - # broken, we should stop execution completely. - if result: - result.error_before_exec = sys.exc_info()[1] - self.showtraceback() - return True - - return False - - async def run_code(self, code_obj, result=None, *, async_=False): - """Execute a code object. - - When an exception occurs, self.showtraceback() is called to display a - traceback. - - Parameters - ---------- - code_obj : code object - A compiled code object, to be executed - result : ExecutionResult, optional - An object to store exceptions that occur during execution. - async_ : Bool (Experimental) - Attempt to run top-level asynchronous code in a default loop. - - Returns - ------- - False : successful execution. - True : an error occurred. - """ - # special value to say that anything above is IPython and should be - # hidden. - __tracebackhide__ = "__ipython_bottom__" - # Set our own excepthook in case the user code tries to call it - # directly, so that the IPython crash handler doesn't get triggered - old_excepthook, sys.excepthook = sys.excepthook, self.excepthook - - # we save the original sys.excepthook in the instance, in case config - # code (such as magics) needs access to it. - self.sys_excepthook = old_excepthook - outflag = True # happens in more places, so it's easier as default - try: - try: - if async_: - await eval(code_obj, self.user_global_ns, self.user_ns) - else: - exec(code_obj, self.user_global_ns, self.user_ns) - finally: - # Reset our crash handler in place - sys.excepthook = old_excepthook - except SystemExit as e: - 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) - except bdb.BdbQuit: - etype, value, tb = sys.exc_info() - if result is not None: - result.error_in_exec = value - # the BdbQuit stops here - except self.custom_exceptions: - etype, value, tb = sys.exc_info() - if result is not None: - result.error_in_exec = value - self.CustomTB(etype, value, tb) - except: - if result is not None: - result.error_in_exec = sys.exc_info()[1] - self.showtraceback(running_compiled_code=True) - else: - outflag = False - return outflag - - # For backwards compatibility - runcode = run_code - - def check_complete(self, code: str) -> Tuple[str, str]: - """Return whether a block of code is ready to execute, or should be continued - - Parameters - ---------- - code : string - Python input code, which can be multiline. - - Returns - ------- - status : str - One of 'complete', 'incomplete', or 'invalid' if source is not a - prefix of valid code. - indent : str - When status is 'incomplete', this is some whitespace to insert on - the next line of the prompt. - """ - status, nspaces = self.input_transformer_manager.check_complete(code) - return status, ' ' * (nspaces or 0) - - #------------------------------------------------------------------------- - # Things related to GUI support and pylab - #------------------------------------------------------------------------- - - active_eventloop = None - - 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 - If given, dictates the choice of matplotlib GUI backend to use - (should be one of IPython's supported backends, 'qt', 'osx', 'tk', - 'gtk', 'wx' or 'inline'), otherwise we use the default chosen by - matplotlib (as dictated by the matplotlib build-time options plus the - user's matplotlibrc configuration file). Note that not all backends - make sense in all contexts, for example a terminal ipython can't - display figures inline. - """ - from matplotlib_inline.backend_inline import configure_inline_support - - 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: - self.pylab_gui_select = gui - # Otherwise if they are different - elif gui != self.pylab_gui_select: - 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) - 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): - """Activate pylab support at runtime. - - This turns on support for matplotlib, preloads into the interactive - 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 - ---------- - gui : optional, string - If given, dictates the choice of matplotlib GUI backend to use - (should be one of IPython's supported backends, 'qt', 'osx', 'tk', - 'gtk', 'wx' or 'inline'), otherwise we use the default chosen by - matplotlib (as dictated by the matplotlib build-time options plus the - user's matplotlibrc configuration file). Note that not all backends - make sense in all contexts, for example a terminal ipython can't - display figures inline. - import_all : optional, bool, default: True - Whether to do `from numpy import *` and `from pylab import *` - in addition to module imports. - welcome_message : deprecated - 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 - # user_ns_hidden with this information. - ns = {} - import_pylab(ns, import_all) - # warn about clobbered names - ignored = {"__builtins__"} - both = set(ns).intersection(self.user_ns).difference(ignored) - clobbered = [ name for name in both if self.user_ns[name] is not ns[name] ] - self.user_ns.update(ns) - self.user_ns_hidden.update(ns) - return gui, backend, clobbered - - #------------------------------------------------------------------------- - # Utilities - #------------------------------------------------------------------------- - - def var_expand(self, cmd, depth=0, formatter=DollarFormatter()): - """Expand python variables in a string. - - The depth argument indicates how many frames above the caller should - be walked to look for the local namespace where to expand variables. - - The global namespace for expansion is always the user's interactive - namespace. - """ - ns = self.user_ns.copy() - try: - frame = sys._getframe(depth+1) - except ValueError: - # This is thrown if there aren't that many frames on the stack, - # e.g. if a script called run_line_magic() directly. - pass - else: - ns.update(frame.f_locals) - - try: - # We have to use .vformat() here, because 'self' is a valid and common - # name, and expanding **ns for .format() would make it collide with - # the 'self' argument of the method. - cmd = formatter.vformat(cmd, args=[], kwargs=ns) - except Exception: - # if formatter couldn't format, just let it go untransformed - pass - return cmd - - def mktempfile(self, data=None, prefix='ipython_edit_'): - """Make a new tempfile and return its filename. - - This makes a call to tempfile.mkstemp (created in a tempfile.mkdtemp), - but it registers the created filename internally so ipython cleans it up - at exit time. - - Optional inputs: - - - data(None): if data is given, it gets written out to the temp file - immediately, and the file is closed again.""" - - dir_path = Path(tempfile.mkdtemp(prefix=prefix)) - self.tempdirs.append(dir_path) - - handle, filename = tempfile.mkstemp(".py", prefix, dir=str(dir_path)) - os.close(handle) # On Windows, there can only be one open handle on a file - - file_path = Path(filename) - self.tempfiles.append(file_path) - - if data: - file_path.write_text(data, encoding="utf-8") - return filename - - def ask_yes_no(self, prompt, default=None, interrupt=None): - if self.quiet: - return True - return ask_yes_no(prompt,default,interrupt) - - def show_usage(self): - """Show a usage message""" - page.page(IPython.core.usage.interactive_usage) - - def extract_input_lines(self, range_str, raw=False): - """Return as a string a set of input history slices. - - Parameters - ---------- - range_str : str - The set of slices is given as a string, like "~5/6-~4/2 4:8 9", - since this function is for use by magic functions which get their - arguments as strings. The number before the / is the session - number: ~n goes n back from the current session. - - If empty string is given, returns history of current session - without the last input. - - raw : bool, optional - By default, the processed input is used. If this is true, the raw - input history is used instead. - - Notes - ----- - Slices can be described with two notations: - - * ``N:M`` -> standard python form, means including items N...(M-1). - * ``N-M`` -> include items N..M (closed endpoint). - """ - lines = self.history_manager.get_range_by_str(range_str, raw=raw) - text = "\n".join(x for _, _, x in lines) - - # Skip the last line, as it's probably the magic that called this - if not range_str: - if "\n" not in text: - text = "" - else: - text = text[: text.rfind("\n")] - - return text - - def find_user_code(self, target, raw=True, py_only=False, skip_encoding_cookie=True, search_ns=False): - """Get a code string from history, file, url, or a string or macro. - - This is mainly used by magic functions. - - Parameters - ---------- - target : str - A string specifying code to retrieve. This will be tried respectively - as: ranges of input history (see %history for syntax), url, - corresponding .py file, filename, or an expression evaluating to a - string or Macro in the user namespace. - - If empty string is given, returns complete history of current - session, without the last line. - - raw : bool - If true (default), retrieve raw history. Has no effect on the other - retrieval mechanisms. - - py_only : bool (default False) - Only try to fetch python code, do not try alternative methods to decode file - if unicode fails. - - Returns - ------- - A string of code. - ValueError is raised if nothing is found, and TypeError if it evaluates - to an object of another type. In each case, .args[0] is a printable - message. - """ - code = self.extract_input_lines(target, raw=raw) # Grab history - if code: - return code - try: - if target.startswith(('http://', 'https://')): - return openpy.read_py_url(target, skip_encoding_cookie=skip_encoding_cookie) - except UnicodeDecodeError as e: - if not py_only : - # Deferred import - from urllib.request import urlopen - response = urlopen(target) - return response.read().decode('latin1') - raise ValueError(("'%s' seem to be unreadable.") % target) from e - - potential_target = [target] - try : - potential_target.insert(0,get_py_filename(target)) - except IOError: - pass - - for tgt in potential_target : - if os.path.isfile(tgt): # Read file - try : - return openpy.read_py_file(tgt, skip_encoding_cookie=skip_encoding_cookie) - except UnicodeDecodeError as e: - if not py_only : - with io_open(tgt,'r', encoding='latin1') as f : - return f.read() - raise ValueError(("'%s' seem to be unreadable.") % target) from e - elif os.path.isdir(os.path.expanduser(tgt)): - raise ValueError("'%s' is a directory, not a regular file." % target) - - if search_ns: - # Inspect namespace to load object source - object_info = self.object_inspect(target, detail_level=1) - if object_info['found'] and object_info['source']: - return object_info['source'] - - try: # User namespace - codeobj = eval(target, self.user_ns) - except Exception as e: - raise ValueError(("'%s' was not found in history, as a file, url, " - "nor in the user namespace.") % target) from e - - if isinstance(codeobj, str): - return codeobj - elif isinstance(codeobj, Macro): - return codeobj.value - - raise TypeError("%s is neither a string nor a macro." % target, - codeobj) - - def _atexit_once(self): - """ - At exist operation that need to be called at most once. - Second call to this function per instance will do nothing. - """ - - if not getattr(self, "_atexit_once_called", False): - self._atexit_once_called = True - # Clear all user namespaces to release all references cleanly. - self.reset(new_session=False) - # Close the history session (this stores the end time and line count) - # this must be *before* the tempfile cleanup, in case of temporary - # history db - self.history_manager.end_session() - self.history_manager = None - - #------------------------------------------------------------------------- - # Things related to IPython exiting - #------------------------------------------------------------------------- - def atexit_operations(self): - """This will be executed at the time of exit. - - Cleanup operations and saving of persistent data that is done - unconditionally by IPython should be performed here. - - For things that may depend on startup flags or platform specifics (such - as having readline or not), register a separate atexit function in the - code that has the appropriate information, rather than trying to - clutter - """ - self._atexit_once() - - # Cleanup all tempfiles and folders left around - for tfile in self.tempfiles: - try: - tfile.unlink() - self.tempfiles.remove(tfile) - except FileNotFoundError: - pass - del self.tempfiles - for tdir in self.tempdirs: - try: - tdir.rmdir() - self.tempdirs.remove(tdir) - except FileNotFoundError: - pass - del self.tempdirs - - # Restore user's cursor - if hasattr(self, "editing_mode") and self.editing_mode == "vi": - sys.stdout.write("\x1b[0 q") - sys.stdout.flush() - - def cleanup(self): - self.restore_sys_module_state() - - - # Overridden in terminal subclass to change prompts - def switch_doctest_mode(self, mode): - pass - - -class InteractiveShellABC(metaclass=abc.ABCMeta): - """An abstract base class for InteractiveShell.""" - -InteractiveShellABC.register(InteractiveShell) diff --git a/contrib/python/ipython/py3/IPython/core/latex_symbols.py b/contrib/python/ipython/py3/IPython/core/latex_symbols.py deleted file mode 100644 index 164d917beb..0000000000 --- a/contrib/python/ipython/py3/IPython/core/latex_symbols.py +++ /dev/null @@ -1,1301 +0,0 @@ -# encoding: utf-8 - -# DO NOT EDIT THIS FILE BY HAND. - -# To update this file, run the script /tools/gen_latex_symbols.py using Python 3 - -# This file is autogenerated from the file: -# https://raw.githubusercontent.com/JuliaLang/julia/master/base/latex_symbols.jl -# This original list is filtered to remove any unicode characters that are not valid -# Python identifiers. - -latex_symbols = { - - "\\euler" : "ℯ", - "\\^a" : "ᵃ", - "\\^b" : "ᵇ", - "\\^c" : "ᶜ", - "\\^d" : "ᵈ", - "\\^e" : "ᵉ", - "\\^f" : "ᶠ", - "\\^g" : "ᵍ", - "\\^h" : "ʰ", - "\\^i" : "ⁱ", - "\\^j" : "ʲ", - "\\^k" : "ᵏ", - "\\^l" : "ˡ", - "\\^m" : "ᵐ", - "\\^n" : "ⁿ", - "\\^o" : "ᵒ", - "\\^p" : "ᵖ", - "\\^r" : "ʳ", - "\\^s" : "ˢ", - "\\^t" : "ᵗ", - "\\^u" : "ᵘ", - "\\^v" : "ᵛ", - "\\^w" : "ʷ", - "\\^x" : "ˣ", - "\\^y" : "ʸ", - "\\^z" : "ᶻ", - "\\^A" : "ᴬ", - "\\^B" : "ᴮ", - "\\^D" : "ᴰ", - "\\^E" : "ᴱ", - "\\^G" : "ᴳ", - "\\^H" : "ᴴ", - "\\^I" : "ᴵ", - "\\^J" : "ᴶ", - "\\^K" : "ᴷ", - "\\^L" : "ᴸ", - "\\^M" : "ᴹ", - "\\^N" : "ᴺ", - "\\^O" : "ᴼ", - "\\^P" : "ᴾ", - "\\^R" : "ᴿ", - "\\^T" : "ᵀ", - "\\^U" : "ᵁ", - "\\^V" : "ⱽ", - "\\^W" : "ᵂ", - "\\^alpha" : "ᵅ", - "\\^beta" : "ᵝ", - "\\^gamma" : "ᵞ", - "\\^delta" : "ᵟ", - "\\^epsilon" : "ᵋ", - "\\^theta" : "ᶿ", - "\\^iota" : "ᶥ", - "\\^phi" : "ᵠ", - "\\^chi" : "ᵡ", - "\\^Phi" : "ᶲ", - "\\_a" : "ₐ", - "\\_e" : "ₑ", - "\\_h" : "ₕ", - "\\_i" : "ᵢ", - "\\_j" : "ⱼ", - "\\_k" : "ₖ", - "\\_l" : "ₗ", - "\\_m" : "ₘ", - "\\_n" : "ₙ", - "\\_o" : "ₒ", - "\\_p" : "ₚ", - "\\_r" : "ᵣ", - "\\_s" : "ₛ", - "\\_t" : "ₜ", - "\\_u" : "ᵤ", - "\\_v" : "ᵥ", - "\\_x" : "ₓ", - "\\_schwa" : "ₔ", - "\\_beta" : "ᵦ", - "\\_gamma" : "ᵧ", - "\\_rho" : "ᵨ", - "\\_phi" : "ᵩ", - "\\_chi" : "ᵪ", - "\\hbar" : "ħ", - "\\sout" : "̶", - "\\ordfeminine" : "ª", - "\\cdotp" : "·", - "\\ordmasculine" : "º", - "\\AA" : "Å", - "\\AE" : "Æ", - "\\DH" : "Ð", - "\\O" : "Ø", - "\\TH" : "Þ", - "\\ss" : "ß", - "\\aa" : "å", - "\\ae" : "æ", - "\\eth" : "ð", - "\\dh" : "ð", - "\\o" : "ø", - "\\th" : "þ", - "\\DJ" : "Đ", - "\\dj" : "đ", - "\\imath" : "ı", - "\\jmath" : "ȷ", - "\\L" : "Ł", - "\\l" : "ł", - "\\NG" : "Ŋ", - "\\ng" : "ŋ", - "\\OE" : "Œ", - "\\oe" : "œ", - "\\hvlig" : "ƕ", - "\\nrleg" : "ƞ", - "\\doublepipe" : "ǂ", - "\\trna" : "ɐ", - "\\trnsa" : "ɒ", - "\\openo" : "ɔ", - "\\rtld" : "ɖ", - "\\schwa" : "ə", - "\\varepsilon" : "ε", - "\\pgamma" : "ɣ", - "\\pbgam" : "ɤ", - "\\trnh" : "ɥ", - "\\btdl" : "ɬ", - "\\rtll" : "ɭ", - "\\trnm" : "ɯ", - "\\trnmlr" : "ɰ", - "\\ltlmr" : "ɱ", - "\\ltln" : "ɲ", - "\\rtln" : "ɳ", - "\\clomeg" : "ɷ", - "\\ltphi" : "ɸ", - "\\trnr" : "ɹ", - "\\trnrl" : "ɺ", - "\\rttrnr" : "ɻ", - "\\rl" : "ɼ", - "\\rtlr" : "ɽ", - "\\fhr" : "ɾ", - "\\rtls" : "ʂ", - "\\esh" : "ʃ", - "\\trnt" : "ʇ", - "\\rtlt" : "ʈ", - "\\pupsil" : "ʊ", - "\\pscrv" : "ʋ", - "\\invv" : "ʌ", - "\\invw" : "ʍ", - "\\trny" : "ʎ", - "\\rtlz" : "ʐ", - "\\yogh" : "ʒ", - "\\glst" : "ʔ", - "\\reglst" : "ʕ", - "\\inglst" : "ʖ", - "\\turnk" : "ʞ", - "\\dyogh" : "ʤ", - "\\tesh" : "ʧ", - "\\rasp" : "ʼ", - "\\verts" : "ˈ", - "\\verti" : "ˌ", - "\\lmrk" : "ː", - "\\hlmrk" : "ˑ", - "\\grave" : "̀", - "\\acute" : "́", - "\\hat" : "̂", - "\\tilde" : "̃", - "\\bar" : "̄", - "\\breve" : "̆", - "\\dot" : "̇", - "\\ddot" : "̈", - "\\ocirc" : "̊", - "\\H" : "̋", - "\\check" : "̌", - "\\palh" : "̡", - "\\rh" : "̢", - "\\c" : "̧", - "\\k" : "̨", - "\\sbbrg" : "̪", - "\\strike" : "̶", - "\\Alpha" : "Α", - "\\Beta" : "Β", - "\\Gamma" : "Γ", - "\\Delta" : "Δ", - "\\Epsilon" : "Ε", - "\\Zeta" : "Ζ", - "\\Eta" : "Η", - "\\Theta" : "Θ", - "\\Iota" : "Ι", - "\\Kappa" : "Κ", - "\\Lambda" : "Λ", - "\\Xi" : "Ξ", - "\\Pi" : "Π", - "\\Rho" : "Ρ", - "\\Sigma" : "Σ", - "\\Tau" : "Τ", - "\\Upsilon" : "Υ", - "\\Phi" : "Φ", - "\\Chi" : "Χ", - "\\Psi" : "Ψ", - "\\Omega" : "Ω", - "\\alpha" : "α", - "\\beta" : "β", - "\\gamma" : "γ", - "\\delta" : "δ", - "\\zeta" : "ζ", - "\\eta" : "η", - "\\theta" : "θ", - "\\iota" : "ι", - "\\kappa" : "κ", - "\\lambda" : "λ", - "\\mu" : "μ", - "\\nu" : "ν", - "\\xi" : "ξ", - "\\pi" : "π", - "\\rho" : "ρ", - "\\varsigma" : "ς", - "\\sigma" : "σ", - "\\tau" : "τ", - "\\upsilon" : "υ", - "\\varphi" : "φ", - "\\chi" : "χ", - "\\psi" : "ψ", - "\\omega" : "ω", - "\\vartheta" : "ϑ", - "\\phi" : "ϕ", - "\\varpi" : "ϖ", - "\\Stigma" : "Ϛ", - "\\Digamma" : "Ϝ", - "\\digamma" : "ϝ", - "\\Koppa" : "Ϟ", - "\\Sampi" : "Ϡ", - "\\varkappa" : "ϰ", - "\\varrho" : "ϱ", - "\\varTheta" : "ϴ", - "\\epsilon" : "ϵ", - "\\dddot" : "⃛", - "\\ddddot" : "⃜", - "\\hslash" : "ℏ", - "\\Im" : "ℑ", - "\\ell" : "ℓ", - "\\wp" : "℘", - "\\Re" : "ℜ", - "\\aleph" : "ℵ", - "\\beth" : "ℶ", - "\\gimel" : "ℷ", - "\\daleth" : "ℸ", - "\\bbPi" : "ℿ", - "\\Zbar" : "Ƶ", - "\\overbar" : "̅", - "\\ovhook" : "̉", - "\\candra" : "̐", - "\\oturnedcomma" : "̒", - "\\ocommatopright" : "̕", - "\\droang" : "̚", - "\\wideutilde" : "̰", - "\\not" : "̸", - "\\upMu" : "Μ", - "\\upNu" : "Ν", - "\\upOmicron" : "Ο", - "\\upepsilon" : "ε", - "\\upomicron" : "ο", - "\\upvarbeta" : "ϐ", - "\\upoldKoppa" : "Ϙ", - "\\upoldkoppa" : "ϙ", - "\\upstigma" : "ϛ", - "\\upkoppa" : "ϟ", - "\\upsampi" : "ϡ", - "\\tieconcat" : "⁀", - "\\leftharpoonaccent" : "⃐", - "\\rightharpoonaccent" : "⃑", - "\\vertoverlay" : "⃒", - "\\overleftarrow" : "⃖", - "\\vec" : "⃗", - "\\overleftrightarrow" : "⃡", - "\\annuity" : "⃧", - "\\threeunderdot" : "⃨", - "\\widebridgeabove" : "⃩", - "\\bbC" : "ℂ", - "\\eulermascheroni" : "ℇ", - "\\scrg" : "ℊ", - "\\scrH" : "ℋ", - "\\frakH" : "ℌ", - "\\bbH" : "ℍ", - "\\planck" : "ℎ", - "\\scrI" : "ℐ", - "\\scrL" : "ℒ", - "\\bbN" : "ℕ", - "\\bbP" : "ℙ", - "\\bbQ" : "ℚ", - "\\scrR" : "ℛ", - "\\bbR" : "ℝ", - "\\bbZ" : "ℤ", - "\\frakZ" : "ℨ", - "\\Angstrom" : "Å", - "\\scrB" : "ℬ", - "\\frakC" : "ℭ", - "\\scre" : "ℯ", - "\\scrE" : "ℰ", - "\\scrF" : "ℱ", - "\\Finv" : "Ⅎ", - "\\scrM" : "ℳ", - "\\scro" : "ℴ", - "\\bbgamma" : "ℽ", - "\\bbGamma" : "ℾ", - "\\bbiD" : "ⅅ", - "\\bbid" : "ⅆ", - "\\bbie" : "ⅇ", - "\\bbii" : "ⅈ", - "\\bbij" : "ⅉ", - "\\bfA" : "𝐀", - "\\bfB" : "𝐁", - "\\bfC" : "𝐂", - "\\bfD" : "𝐃", - "\\bfE" : "𝐄", - "\\bfF" : "𝐅", - "\\bfG" : "𝐆", - "\\bfH" : "𝐇", - "\\bfI" : "𝐈", - "\\bfJ" : "𝐉", - "\\bfK" : "𝐊", - "\\bfL" : "𝐋", - "\\bfM" : "𝐌", - "\\bfN" : "𝐍", - "\\bfO" : "𝐎", - "\\bfP" : "𝐏", - "\\bfQ" : "𝐐", - "\\bfR" : "𝐑", - "\\bfS" : "𝐒", - "\\bfT" : "𝐓", - "\\bfU" : "𝐔", - "\\bfV" : "𝐕", - "\\bfW" : "𝐖", - "\\bfX" : "𝐗", - "\\bfY" : "𝐘", - "\\bfZ" : "𝐙", - "\\bfa" : "𝐚", - "\\bfb" : "𝐛", - "\\bfc" : "𝐜", - "\\bfd" : "𝐝", - "\\bfe" : "𝐞", - "\\bff" : "𝐟", - "\\bfg" : "𝐠", - "\\bfh" : "𝐡", - "\\bfi" : "𝐢", - "\\bfj" : "𝐣", - "\\bfk" : "𝐤", - "\\bfl" : "𝐥", - "\\bfm" : "𝐦", - "\\bfn" : "𝐧", - "\\bfo" : "𝐨", - "\\bfp" : "𝐩", - "\\bfq" : "𝐪", - "\\bfr" : "𝐫", - "\\bfs" : "𝐬", - "\\bft" : "𝐭", - "\\bfu" : "𝐮", - "\\bfv" : "𝐯", - "\\bfw" : "𝐰", - "\\bfx" : "𝐱", - "\\bfy" : "𝐲", - "\\bfz" : "𝐳", - "\\itA" : "𝐴", - "\\itB" : "𝐵", - "\\itC" : "𝐶", - "\\itD" : "𝐷", - "\\itE" : "𝐸", - "\\itF" : "𝐹", - "\\itG" : "𝐺", - "\\itH" : "𝐻", - "\\itI" : "𝐼", - "\\itJ" : "𝐽", - "\\itK" : "𝐾", - "\\itL" : "𝐿", - "\\itM" : "𝑀", - "\\itN" : "𝑁", - "\\itO" : "𝑂", - "\\itP" : "𝑃", - "\\itQ" : "𝑄", - "\\itR" : "𝑅", - "\\itS" : "𝑆", - "\\itT" : "𝑇", - "\\itU" : "𝑈", - "\\itV" : "𝑉", - "\\itW" : "𝑊", - "\\itX" : "𝑋", - "\\itY" : "𝑌", - "\\itZ" : "𝑍", - "\\ita" : "𝑎", - "\\itb" : "𝑏", - "\\itc" : "𝑐", - "\\itd" : "𝑑", - "\\ite" : "𝑒", - "\\itf" : "𝑓", - "\\itg" : "𝑔", - "\\iti" : "𝑖", - "\\itj" : "𝑗", - "\\itk" : "𝑘", - "\\itl" : "𝑙", - "\\itm" : "𝑚", - "\\itn" : "𝑛", - "\\ito" : "𝑜", - "\\itp" : "𝑝", - "\\itq" : "𝑞", - "\\itr" : "𝑟", - "\\its" : "𝑠", - "\\itt" : "𝑡", - "\\itu" : "𝑢", - "\\itv" : "𝑣", - "\\itw" : "𝑤", - "\\itx" : "𝑥", - "\\ity" : "𝑦", - "\\itz" : "𝑧", - "\\biA" : "𝑨", - "\\biB" : "𝑩", - "\\biC" : "𝑪", - "\\biD" : "𝑫", - "\\biE" : "𝑬", - "\\biF" : "𝑭", - "\\biG" : "𝑮", - "\\biH" : "𝑯", - "\\biI" : "𝑰", - "\\biJ" : "𝑱", - "\\biK" : "𝑲", - "\\biL" : "𝑳", - "\\biM" : "𝑴", - "\\biN" : "𝑵", - "\\biO" : "𝑶", - "\\biP" : "𝑷", - "\\biQ" : "𝑸", - "\\biR" : "𝑹", - "\\biS" : "𝑺", - "\\biT" : "𝑻", - "\\biU" : "𝑼", - "\\biV" : "𝑽", - "\\biW" : "𝑾", - "\\biX" : "𝑿", - "\\biY" : "𝒀", - "\\biZ" : "𝒁", - "\\bia" : "𝒂", - "\\bib" : "𝒃", - "\\bic" : "𝒄", - "\\bid" : "𝒅", - "\\bie" : "𝒆", - "\\bif" : "𝒇", - "\\big" : "𝒈", - "\\bih" : "𝒉", - "\\bii" : "𝒊", - "\\bij" : "𝒋", - "\\bik" : "𝒌", - "\\bil" : "𝒍", - "\\bim" : "𝒎", - "\\bin" : "𝒏", - "\\bio" : "𝒐", - "\\bip" : "𝒑", - "\\biq" : "𝒒", - "\\bir" : "𝒓", - "\\bis" : "𝒔", - "\\bit" : "𝒕", - "\\biu" : "𝒖", - "\\biv" : "𝒗", - "\\biw" : "𝒘", - "\\bix" : "𝒙", - "\\biy" : "𝒚", - "\\biz" : "𝒛", - "\\scrA" : "𝒜", - "\\scrC" : "𝒞", - "\\scrD" : "𝒟", - "\\scrG" : "𝒢", - "\\scrJ" : "𝒥", - "\\scrK" : "𝒦", - "\\scrN" : "𝒩", - "\\scrO" : "𝒪", - "\\scrP" : "𝒫", - "\\scrQ" : "𝒬", - "\\scrS" : "𝒮", - "\\scrT" : "𝒯", - "\\scrU" : "𝒰", - "\\scrV" : "𝒱", - "\\scrW" : "𝒲", - "\\scrX" : "𝒳", - "\\scrY" : "𝒴", - "\\scrZ" : "𝒵", - "\\scra" : "𝒶", - "\\scrb" : "𝒷", - "\\scrc" : "𝒸", - "\\scrd" : "𝒹", - "\\scrf" : "𝒻", - "\\scrh" : "𝒽", - "\\scri" : "𝒾", - "\\scrj" : "𝒿", - "\\scrk" : "𝓀", - "\\scrm" : "𝓂", - "\\scrn" : "𝓃", - "\\scrp" : "𝓅", - "\\scrq" : "𝓆", - "\\scrr" : "𝓇", - "\\scrs" : "𝓈", - "\\scrt" : "𝓉", - "\\scru" : "𝓊", - "\\scrv" : "𝓋", - "\\scrw" : "𝓌", - "\\scrx" : "𝓍", - "\\scry" : "𝓎", - "\\scrz" : "𝓏", - "\\bscrA" : "𝓐", - "\\bscrB" : "𝓑", - "\\bscrC" : "𝓒", - "\\bscrD" : "𝓓", - "\\bscrE" : "𝓔", - "\\bscrF" : "𝓕", - "\\bscrG" : "𝓖", - "\\bscrH" : "𝓗", - "\\bscrI" : "𝓘", - "\\bscrJ" : "𝓙", - "\\bscrK" : "𝓚", - "\\bscrL" : "𝓛", - "\\bscrM" : "𝓜", - "\\bscrN" : "𝓝", - "\\bscrO" : "𝓞", - "\\bscrP" : "𝓟", - "\\bscrQ" : "𝓠", - "\\bscrR" : "𝓡", - "\\bscrS" : "𝓢", - "\\bscrT" : "𝓣", - "\\bscrU" : "𝓤", - "\\bscrV" : "𝓥", - "\\bscrW" : "𝓦", - "\\bscrX" : "𝓧", - "\\bscrY" : "𝓨", - "\\bscrZ" : "𝓩", - "\\bscra" : "𝓪", - "\\bscrb" : "𝓫", - "\\bscrc" : "𝓬", - "\\bscrd" : "𝓭", - "\\bscre" : "𝓮", - "\\bscrf" : "𝓯", - "\\bscrg" : "𝓰", - "\\bscrh" : "𝓱", - "\\bscri" : "𝓲", - "\\bscrj" : "𝓳", - "\\bscrk" : "𝓴", - "\\bscrl" : "𝓵", - "\\bscrm" : "𝓶", - "\\bscrn" : "𝓷", - "\\bscro" : "𝓸", - "\\bscrp" : "𝓹", - "\\bscrq" : "𝓺", - "\\bscrr" : "𝓻", - "\\bscrs" : "𝓼", - "\\bscrt" : "𝓽", - "\\bscru" : "𝓾", - "\\bscrv" : "𝓿", - "\\bscrw" : "𝔀", - "\\bscrx" : "𝔁", - "\\bscry" : "𝔂", - "\\bscrz" : "𝔃", - "\\frakA" : "𝔄", - "\\frakB" : "𝔅", - "\\frakD" : "𝔇", - "\\frakE" : "𝔈", - "\\frakF" : "𝔉", - "\\frakG" : "𝔊", - "\\frakJ" : "𝔍", - "\\frakK" : "𝔎", - "\\frakL" : "𝔏", - "\\frakM" : "𝔐", - "\\frakN" : "𝔑", - "\\frakO" : "𝔒", - "\\frakP" : "𝔓", - "\\frakQ" : "𝔔", - "\\frakS" : "𝔖", - "\\frakT" : "𝔗", - "\\frakU" : "𝔘", - "\\frakV" : "𝔙", - "\\frakW" : "𝔚", - "\\frakX" : "𝔛", - "\\frakY" : "𝔜", - "\\fraka" : "𝔞", - "\\frakb" : "𝔟", - "\\frakc" : "𝔠", - "\\frakd" : "𝔡", - "\\frake" : "𝔢", - "\\frakf" : "𝔣", - "\\frakg" : "𝔤", - "\\frakh" : "𝔥", - "\\fraki" : "𝔦", - "\\frakj" : "𝔧", - "\\frakk" : "𝔨", - "\\frakl" : "𝔩", - "\\frakm" : "𝔪", - "\\frakn" : "𝔫", - "\\frako" : "𝔬", - "\\frakp" : "𝔭", - "\\frakq" : "𝔮", - "\\frakr" : "𝔯", - "\\fraks" : "𝔰", - "\\frakt" : "𝔱", - "\\fraku" : "𝔲", - "\\frakv" : "𝔳", - "\\frakw" : "𝔴", - "\\frakx" : "𝔵", - "\\fraky" : "𝔶", - "\\frakz" : "𝔷", - "\\bbA" : "𝔸", - "\\bbB" : "𝔹", - "\\bbD" : "𝔻", - "\\bbE" : "𝔼", - "\\bbF" : "𝔽", - "\\bbG" : "𝔾", - "\\bbI" : "𝕀", - "\\bbJ" : "𝕁", - "\\bbK" : "𝕂", - "\\bbL" : "𝕃", - "\\bbM" : "𝕄", - "\\bbO" : "𝕆", - "\\bbS" : "𝕊", - "\\bbT" : "𝕋", - "\\bbU" : "𝕌", - "\\bbV" : "𝕍", - "\\bbW" : "𝕎", - "\\bbX" : "𝕏", - "\\bbY" : "𝕐", - "\\bba" : "𝕒", - "\\bbb" : "𝕓", - "\\bbc" : "𝕔", - "\\bbd" : "𝕕", - "\\bbe" : "𝕖", - "\\bbf" : "𝕗", - "\\bbg" : "𝕘", - "\\bbh" : "𝕙", - "\\bbi" : "𝕚", - "\\bbj" : "𝕛", - "\\bbk" : "𝕜", - "\\bbl" : "𝕝", - "\\bbm" : "𝕞", - "\\bbn" : "𝕟", - "\\bbo" : "𝕠", - "\\bbp" : "𝕡", - "\\bbq" : "𝕢", - "\\bbr" : "𝕣", - "\\bbs" : "𝕤", - "\\bbt" : "𝕥", - "\\bbu" : "𝕦", - "\\bbv" : "𝕧", - "\\bbw" : "𝕨", - "\\bbx" : "𝕩", - "\\bby" : "𝕪", - "\\bbz" : "𝕫", - "\\bfrakA" : "𝕬", - "\\bfrakB" : "𝕭", - "\\bfrakC" : "𝕮", - "\\bfrakD" : "𝕯", - "\\bfrakE" : "𝕰", - "\\bfrakF" : "𝕱", - "\\bfrakG" : "𝕲", - "\\bfrakH" : "𝕳", - "\\bfrakI" : "𝕴", - "\\bfrakJ" : "𝕵", - "\\bfrakK" : "𝕶", - "\\bfrakL" : "𝕷", - "\\bfrakM" : "𝕸", - "\\bfrakN" : "𝕹", - "\\bfrakO" : "𝕺", - "\\bfrakP" : "𝕻", - "\\bfrakQ" : "𝕼", - "\\bfrakR" : "𝕽", - "\\bfrakS" : "𝕾", - "\\bfrakT" : "𝕿", - "\\bfrakU" : "𝖀", - "\\bfrakV" : "𝖁", - "\\bfrakW" : "𝖂", - "\\bfrakX" : "𝖃", - "\\bfrakY" : "𝖄", - "\\bfrakZ" : "𝖅", - "\\bfraka" : "𝖆", - "\\bfrakb" : "𝖇", - "\\bfrakc" : "𝖈", - "\\bfrakd" : "𝖉", - "\\bfrake" : "𝖊", - "\\bfrakf" : "𝖋", - "\\bfrakg" : "𝖌", - "\\bfrakh" : "𝖍", - "\\bfraki" : "𝖎", - "\\bfrakj" : "𝖏", - "\\bfrakk" : "𝖐", - "\\bfrakl" : "𝖑", - "\\bfrakm" : "𝖒", - "\\bfrakn" : "𝖓", - "\\bfrako" : "𝖔", - "\\bfrakp" : "𝖕", - "\\bfrakq" : "𝖖", - "\\bfrakr" : "𝖗", - "\\bfraks" : "𝖘", - "\\bfrakt" : "𝖙", - "\\bfraku" : "𝖚", - "\\bfrakv" : "𝖛", - "\\bfrakw" : "𝖜", - "\\bfrakx" : "𝖝", - "\\bfraky" : "𝖞", - "\\bfrakz" : "𝖟", - "\\sansA" : "𝖠", - "\\sansB" : "𝖡", - "\\sansC" : "𝖢", - "\\sansD" : "𝖣", - "\\sansE" : "𝖤", - "\\sansF" : "𝖥", - "\\sansG" : "𝖦", - "\\sansH" : "𝖧", - "\\sansI" : "𝖨", - "\\sansJ" : "𝖩", - "\\sansK" : "𝖪", - "\\sansL" : "𝖫", - "\\sansM" : "𝖬", - "\\sansN" : "𝖭", - "\\sansO" : "𝖮", - "\\sansP" : "𝖯", - "\\sansQ" : "𝖰", - "\\sansR" : "𝖱", - "\\sansS" : "𝖲", - "\\sansT" : "𝖳", - "\\sansU" : "𝖴", - "\\sansV" : "𝖵", - "\\sansW" : "𝖶", - "\\sansX" : "𝖷", - "\\sansY" : "𝖸", - "\\sansZ" : "𝖹", - "\\sansa" : "𝖺", - "\\sansb" : "𝖻", - "\\sansc" : "𝖼", - "\\sansd" : "𝖽", - "\\sanse" : "𝖾", - "\\sansf" : "𝖿", - "\\sansg" : "𝗀", - "\\sansh" : "𝗁", - "\\sansi" : "𝗂", - "\\sansj" : "𝗃", - "\\sansk" : "𝗄", - "\\sansl" : "𝗅", - "\\sansm" : "𝗆", - "\\sansn" : "𝗇", - "\\sanso" : "𝗈", - "\\sansp" : "𝗉", - "\\sansq" : "𝗊", - "\\sansr" : "𝗋", - "\\sanss" : "𝗌", - "\\sanst" : "𝗍", - "\\sansu" : "𝗎", - "\\sansv" : "𝗏", - "\\sansw" : "𝗐", - "\\sansx" : "𝗑", - "\\sansy" : "𝗒", - "\\sansz" : "𝗓", - "\\bsansA" : "𝗔", - "\\bsansB" : "𝗕", - "\\bsansC" : "𝗖", - "\\bsansD" : "𝗗", - "\\bsansE" : "𝗘", - "\\bsansF" : "𝗙", - "\\bsansG" : "𝗚", - "\\bsansH" : "𝗛", - "\\bsansI" : "𝗜", - "\\bsansJ" : "𝗝", - "\\bsansK" : "𝗞", - "\\bsansL" : "𝗟", - "\\bsansM" : "𝗠", - "\\bsansN" : "𝗡", - "\\bsansO" : "𝗢", - "\\bsansP" : "𝗣", - "\\bsansQ" : "𝗤", - "\\bsansR" : "𝗥", - "\\bsansS" : "𝗦", - "\\bsansT" : "𝗧", - "\\bsansU" : "𝗨", - "\\bsansV" : "𝗩", - "\\bsansW" : "𝗪", - "\\bsansX" : "𝗫", - "\\bsansY" : "𝗬", - "\\bsansZ" : "𝗭", - "\\bsansa" : "𝗮", - "\\bsansb" : "𝗯", - "\\bsansc" : "𝗰", - "\\bsansd" : "𝗱", - "\\bsanse" : "𝗲", - "\\bsansf" : "𝗳", - "\\bsansg" : "𝗴", - "\\bsansh" : "𝗵", - "\\bsansi" : "𝗶", - "\\bsansj" : "𝗷", - "\\bsansk" : "𝗸", - "\\bsansl" : "𝗹", - "\\bsansm" : "𝗺", - "\\bsansn" : "𝗻", - "\\bsanso" : "𝗼", - "\\bsansp" : "𝗽", - "\\bsansq" : "𝗾", - "\\bsansr" : "𝗿", - "\\bsanss" : "𝘀", - "\\bsanst" : "𝘁", - "\\bsansu" : "𝘂", - "\\bsansv" : "𝘃", - "\\bsansw" : "𝘄", - "\\bsansx" : "𝘅", - "\\bsansy" : "𝘆", - "\\bsansz" : "𝘇", - "\\isansA" : "𝘈", - "\\isansB" : "𝘉", - "\\isansC" : "𝘊", - "\\isansD" : "𝘋", - "\\isansE" : "𝘌", - "\\isansF" : "𝘍", - "\\isansG" : "𝘎", - "\\isansH" : "𝘏", - "\\isansI" : "𝘐", - "\\isansJ" : "𝘑", - "\\isansK" : "𝘒", - "\\isansL" : "𝘓", - "\\isansM" : "𝘔", - "\\isansN" : "𝘕", - "\\isansO" : "𝘖", - "\\isansP" : "𝘗", - "\\isansQ" : "𝘘", - "\\isansR" : "𝘙", - "\\isansS" : "𝘚", - "\\isansT" : "𝘛", - "\\isansU" : "𝘜", - "\\isansV" : "𝘝", - "\\isansW" : "𝘞", - "\\isansX" : "𝘟", - "\\isansY" : "𝘠", - "\\isansZ" : "𝘡", - "\\isansa" : "𝘢", - "\\isansb" : "𝘣", - "\\isansc" : "𝘤", - "\\isansd" : "𝘥", - "\\isanse" : "𝘦", - "\\isansf" : "𝘧", - "\\isansg" : "𝘨", - "\\isansh" : "𝘩", - "\\isansi" : "𝘪", - "\\isansj" : "𝘫", - "\\isansk" : "𝘬", - "\\isansl" : "𝘭", - "\\isansm" : "𝘮", - "\\isansn" : "𝘯", - "\\isanso" : "𝘰", - "\\isansp" : "𝘱", - "\\isansq" : "𝘲", - "\\isansr" : "𝘳", - "\\isanss" : "𝘴", - "\\isanst" : "𝘵", - "\\isansu" : "𝘶", - "\\isansv" : "𝘷", - "\\isansw" : "𝘸", - "\\isansx" : "𝘹", - "\\isansy" : "𝘺", - "\\isansz" : "𝘻", - "\\bisansA" : "𝘼", - "\\bisansB" : "𝘽", - "\\bisansC" : "𝘾", - "\\bisansD" : "𝘿", - "\\bisansE" : "𝙀", - "\\bisansF" : "𝙁", - "\\bisansG" : "𝙂", - "\\bisansH" : "𝙃", - "\\bisansI" : "𝙄", - "\\bisansJ" : "𝙅", - "\\bisansK" : "𝙆", - "\\bisansL" : "𝙇", - "\\bisansM" : "𝙈", - "\\bisansN" : "𝙉", - "\\bisansO" : "𝙊", - "\\bisansP" : "𝙋", - "\\bisansQ" : "𝙌", - "\\bisansR" : "𝙍", - "\\bisansS" : "𝙎", - "\\bisansT" : "𝙏", - "\\bisansU" : "𝙐", - "\\bisansV" : "𝙑", - "\\bisansW" : "𝙒", - "\\bisansX" : "𝙓", - "\\bisansY" : "𝙔", - "\\bisansZ" : "𝙕", - "\\bisansa" : "𝙖", - "\\bisansb" : "𝙗", - "\\bisansc" : "𝙘", - "\\bisansd" : "𝙙", - "\\bisanse" : "𝙚", - "\\bisansf" : "𝙛", - "\\bisansg" : "𝙜", - "\\bisansh" : "𝙝", - "\\bisansi" : "𝙞", - "\\bisansj" : "𝙟", - "\\bisansk" : "𝙠", - "\\bisansl" : "𝙡", - "\\bisansm" : "𝙢", - "\\bisansn" : "𝙣", - "\\bisanso" : "𝙤", - "\\bisansp" : "𝙥", - "\\bisansq" : "𝙦", - "\\bisansr" : "𝙧", - "\\bisanss" : "𝙨", - "\\bisanst" : "𝙩", - "\\bisansu" : "𝙪", - "\\bisansv" : "𝙫", - "\\bisansw" : "𝙬", - "\\bisansx" : "𝙭", - "\\bisansy" : "𝙮", - "\\bisansz" : "𝙯", - "\\ttA" : "𝙰", - "\\ttB" : "𝙱", - "\\ttC" : "𝙲", - "\\ttD" : "𝙳", - "\\ttE" : "𝙴", - "\\ttF" : "𝙵", - "\\ttG" : "𝙶", - "\\ttH" : "𝙷", - "\\ttI" : "𝙸", - "\\ttJ" : "𝙹", - "\\ttK" : "𝙺", - "\\ttL" : "𝙻", - "\\ttM" : "𝙼", - "\\ttN" : "𝙽", - "\\ttO" : "𝙾", - "\\ttP" : "𝙿", - "\\ttQ" : "𝚀", - "\\ttR" : "𝚁", - "\\ttS" : "𝚂", - "\\ttT" : "𝚃", - "\\ttU" : "𝚄", - "\\ttV" : "𝚅", - "\\ttW" : "𝚆", - "\\ttX" : "𝚇", - "\\ttY" : "𝚈", - "\\ttZ" : "𝚉", - "\\tta" : "𝚊", - "\\ttb" : "𝚋", - "\\ttc" : "𝚌", - "\\ttd" : "𝚍", - "\\tte" : "𝚎", - "\\ttf" : "𝚏", - "\\ttg" : "𝚐", - "\\tth" : "𝚑", - "\\tti" : "𝚒", - "\\ttj" : "𝚓", - "\\ttk" : "𝚔", - "\\ttl" : "𝚕", - "\\ttm" : "𝚖", - "\\ttn" : "𝚗", - "\\tto" : "𝚘", - "\\ttp" : "𝚙", - "\\ttq" : "𝚚", - "\\ttr" : "𝚛", - "\\tts" : "𝚜", - "\\ttt" : "𝚝", - "\\ttu" : "𝚞", - "\\ttv" : "𝚟", - "\\ttw" : "𝚠", - "\\ttx" : "𝚡", - "\\tty" : "𝚢", - "\\ttz" : "𝚣", - "\\bfAlpha" : "𝚨", - "\\bfBeta" : "𝚩", - "\\bfGamma" : "𝚪", - "\\bfDelta" : "𝚫", - "\\bfEpsilon" : "𝚬", - "\\bfZeta" : "𝚭", - "\\bfEta" : "𝚮", - "\\bfTheta" : "𝚯", - "\\bfIota" : "𝚰", - "\\bfKappa" : "𝚱", - "\\bfLambda" : "𝚲", - "\\bfMu" : "𝚳", - "\\bfNu" : "𝚴", - "\\bfXi" : "𝚵", - "\\bfOmicron" : "𝚶", - "\\bfPi" : "𝚷", - "\\bfRho" : "𝚸", - "\\bfvarTheta" : "𝚹", - "\\bfSigma" : "𝚺", - "\\bfTau" : "𝚻", - "\\bfUpsilon" : "𝚼", - "\\bfPhi" : "𝚽", - "\\bfChi" : "𝚾", - "\\bfPsi" : "𝚿", - "\\bfOmega" : "𝛀", - "\\bfalpha" : "𝛂", - "\\bfbeta" : "𝛃", - "\\bfgamma" : "𝛄", - "\\bfdelta" : "𝛅", - "\\bfepsilon" : "𝛆", - "\\bfzeta" : "𝛇", - "\\bfeta" : "𝛈", - "\\bftheta" : "𝛉", - "\\bfiota" : "𝛊", - "\\bfkappa" : "𝛋", - "\\bflambda" : "𝛌", - "\\bfmu" : "𝛍", - "\\bfnu" : "𝛎", - "\\bfxi" : "𝛏", - "\\bfomicron" : "𝛐", - "\\bfpi" : "𝛑", - "\\bfrho" : "𝛒", - "\\bfvarsigma" : "𝛓", - "\\bfsigma" : "𝛔", - "\\bftau" : "𝛕", - "\\bfupsilon" : "𝛖", - "\\bfvarphi" : "𝛗", - "\\bfchi" : "𝛘", - "\\bfpsi" : "𝛙", - "\\bfomega" : "𝛚", - "\\bfvarepsilon" : "𝛜", - "\\bfvartheta" : "𝛝", - "\\bfvarkappa" : "𝛞", - "\\bfphi" : "𝛟", - "\\bfvarrho" : "𝛠", - "\\bfvarpi" : "𝛡", - "\\itAlpha" : "𝛢", - "\\itBeta" : "𝛣", - "\\itGamma" : "𝛤", - "\\itDelta" : "𝛥", - "\\itEpsilon" : "𝛦", - "\\itZeta" : "𝛧", - "\\itEta" : "𝛨", - "\\itTheta" : "𝛩", - "\\itIota" : "𝛪", - "\\itKappa" : "𝛫", - "\\itLambda" : "𝛬", - "\\itMu" : "𝛭", - "\\itNu" : "𝛮", - "\\itXi" : "𝛯", - "\\itOmicron" : "𝛰", - "\\itPi" : "𝛱", - "\\itRho" : "𝛲", - "\\itvarTheta" : "𝛳", - "\\itSigma" : "𝛴", - "\\itTau" : "𝛵", - "\\itUpsilon" : "𝛶", - "\\itPhi" : "𝛷", - "\\itChi" : "𝛸", - "\\itPsi" : "𝛹", - "\\itOmega" : "𝛺", - "\\italpha" : "𝛼", - "\\itbeta" : "𝛽", - "\\itgamma" : "𝛾", - "\\itdelta" : "𝛿", - "\\itepsilon" : "𝜀", - "\\itzeta" : "𝜁", - "\\iteta" : "𝜂", - "\\ittheta" : "𝜃", - "\\itiota" : "𝜄", - "\\itkappa" : "𝜅", - "\\itlambda" : "𝜆", - "\\itmu" : "𝜇", - "\\itnu" : "𝜈", - "\\itxi" : "𝜉", - "\\itomicron" : "𝜊", - "\\itpi" : "𝜋", - "\\itrho" : "𝜌", - "\\itvarsigma" : "𝜍", - "\\itsigma" : "𝜎", - "\\ittau" : "𝜏", - "\\itupsilon" : "𝜐", - "\\itphi" : "𝜑", - "\\itchi" : "𝜒", - "\\itpsi" : "𝜓", - "\\itomega" : "𝜔", - "\\itvarepsilon" : "𝜖", - "\\itvartheta" : "𝜗", - "\\itvarkappa" : "𝜘", - "\\itvarphi" : "𝜙", - "\\itvarrho" : "𝜚", - "\\itvarpi" : "𝜛", - "\\biAlpha" : "𝜜", - "\\biBeta" : "𝜝", - "\\biGamma" : "𝜞", - "\\biDelta" : "𝜟", - "\\biEpsilon" : "𝜠", - "\\biZeta" : "𝜡", - "\\biEta" : "𝜢", - "\\biTheta" : "𝜣", - "\\biIota" : "𝜤", - "\\biKappa" : "𝜥", - "\\biLambda" : "𝜦", - "\\biMu" : "𝜧", - "\\biNu" : "𝜨", - "\\biXi" : "𝜩", - "\\biOmicron" : "𝜪", - "\\biPi" : "𝜫", - "\\biRho" : "𝜬", - "\\bivarTheta" : "𝜭", - "\\biSigma" : "𝜮", - "\\biTau" : "𝜯", - "\\biUpsilon" : "𝜰", - "\\biPhi" : "𝜱", - "\\biChi" : "𝜲", - "\\biPsi" : "𝜳", - "\\biOmega" : "𝜴", - "\\bialpha" : "𝜶", - "\\bibeta" : "𝜷", - "\\bigamma" : "𝜸", - "\\bidelta" : "𝜹", - "\\biepsilon" : "𝜺", - "\\bizeta" : "𝜻", - "\\bieta" : "𝜼", - "\\bitheta" : "𝜽", - "\\biiota" : "𝜾", - "\\bikappa" : "𝜿", - "\\bilambda" : "𝝀", - "\\bimu" : "𝝁", - "\\binu" : "𝝂", - "\\bixi" : "𝝃", - "\\biomicron" : "𝝄", - "\\bipi" : "𝝅", - "\\birho" : "𝝆", - "\\bivarsigma" : "𝝇", - "\\bisigma" : "𝝈", - "\\bitau" : "𝝉", - "\\biupsilon" : "𝝊", - "\\biphi" : "𝝋", - "\\bichi" : "𝝌", - "\\bipsi" : "𝝍", - "\\biomega" : "𝝎", - "\\bivarepsilon" : "𝝐", - "\\bivartheta" : "𝝑", - "\\bivarkappa" : "𝝒", - "\\bivarphi" : "𝝓", - "\\bivarrho" : "𝝔", - "\\bivarpi" : "𝝕", - "\\bsansAlpha" : "𝝖", - "\\bsansBeta" : "𝝗", - "\\bsansGamma" : "𝝘", - "\\bsansDelta" : "𝝙", - "\\bsansEpsilon" : "𝝚", - "\\bsansZeta" : "𝝛", - "\\bsansEta" : "𝝜", - "\\bsansTheta" : "𝝝", - "\\bsansIota" : "𝝞", - "\\bsansKappa" : "𝝟", - "\\bsansLambda" : "𝝠", - "\\bsansMu" : "𝝡", - "\\bsansNu" : "𝝢", - "\\bsansXi" : "𝝣", - "\\bsansOmicron" : "𝝤", - "\\bsansPi" : "𝝥", - "\\bsansRho" : "𝝦", - "\\bsansvarTheta" : "𝝧", - "\\bsansSigma" : "𝝨", - "\\bsansTau" : "𝝩", - "\\bsansUpsilon" : "𝝪", - "\\bsansPhi" : "𝝫", - "\\bsansChi" : "𝝬", - "\\bsansPsi" : "𝝭", - "\\bsansOmega" : "𝝮", - "\\bsansalpha" : "𝝰", - "\\bsansbeta" : "𝝱", - "\\bsansgamma" : "𝝲", - "\\bsansdelta" : "𝝳", - "\\bsansepsilon" : "𝝴", - "\\bsanszeta" : "𝝵", - "\\bsanseta" : "𝝶", - "\\bsanstheta" : "𝝷", - "\\bsansiota" : "𝝸", - "\\bsanskappa" : "𝝹", - "\\bsanslambda" : "𝝺", - "\\bsansmu" : "𝝻", - "\\bsansnu" : "𝝼", - "\\bsansxi" : "𝝽", - "\\bsansomicron" : "𝝾", - "\\bsanspi" : "𝝿", - "\\bsansrho" : "𝞀", - "\\bsansvarsigma" : "𝞁", - "\\bsanssigma" : "𝞂", - "\\bsanstau" : "𝞃", - "\\bsansupsilon" : "𝞄", - "\\bsansphi" : "𝞅", - "\\bsanschi" : "𝞆", - "\\bsanspsi" : "𝞇", - "\\bsansomega" : "𝞈", - "\\bsansvarepsilon" : "𝞊", - "\\bsansvartheta" : "𝞋", - "\\bsansvarkappa" : "𝞌", - "\\bsansvarphi" : "𝞍", - "\\bsansvarrho" : "𝞎", - "\\bsansvarpi" : "𝞏", - "\\bisansAlpha" : "𝞐", - "\\bisansBeta" : "𝞑", - "\\bisansGamma" : "𝞒", - "\\bisansDelta" : "𝞓", - "\\bisansEpsilon" : "𝞔", - "\\bisansZeta" : "𝞕", - "\\bisansEta" : "𝞖", - "\\bisansTheta" : "𝞗", - "\\bisansIota" : "𝞘", - "\\bisansKappa" : "𝞙", - "\\bisansLambda" : "𝞚", - "\\bisansMu" : "𝞛", - "\\bisansNu" : "𝞜", - "\\bisansXi" : "𝞝", - "\\bisansOmicron" : "𝞞", - "\\bisansPi" : "𝞟", - "\\bisansRho" : "𝞠", - "\\bisansvarTheta" : "𝞡", - "\\bisansSigma" : "𝞢", - "\\bisansTau" : "𝞣", - "\\bisansUpsilon" : "𝞤", - "\\bisansPhi" : "𝞥", - "\\bisansChi" : "𝞦", - "\\bisansPsi" : "𝞧", - "\\bisansOmega" : "𝞨", - "\\bisansalpha" : "𝞪", - "\\bisansbeta" : "𝞫", - "\\bisansgamma" : "𝞬", - "\\bisansdelta" : "𝞭", - "\\bisansepsilon" : "𝞮", - "\\bisanszeta" : "𝞯", - "\\bisanseta" : "𝞰", - "\\bisanstheta" : "𝞱", - "\\bisansiota" : "𝞲", - "\\bisanskappa" : "𝞳", - "\\bisanslambda" : "𝞴", - "\\bisansmu" : "𝞵", - "\\bisansnu" : "𝞶", - "\\bisansxi" : "𝞷", - "\\bisansomicron" : "𝞸", - "\\bisanspi" : "𝞹", - "\\bisansrho" : "𝞺", - "\\bisansvarsigma" : "𝞻", - "\\bisanssigma" : "𝞼", - "\\bisanstau" : "𝞽", - "\\bisansupsilon" : "𝞾", - "\\bisansphi" : "𝞿", - "\\bisanschi" : "𝟀", - "\\bisanspsi" : "𝟁", - "\\bisansomega" : "𝟂", - "\\bisansvarepsilon" : "𝟄", - "\\bisansvartheta" : "𝟅", - "\\bisansvarkappa" : "𝟆", - "\\bisansvarphi" : "𝟇", - "\\bisansvarrho" : "𝟈", - "\\bisansvarpi" : "𝟉", - "\\bfzero" : "𝟎", - "\\bfone" : "𝟏", - "\\bftwo" : "𝟐", - "\\bfthree" : "𝟑", - "\\bffour" : "𝟒", - "\\bffive" : "𝟓", - "\\bfsix" : "𝟔", - "\\bfseven" : "𝟕", - "\\bfeight" : "𝟖", - "\\bfnine" : "𝟗", - "\\bbzero" : "𝟘", - "\\bbone" : "𝟙", - "\\bbtwo" : "𝟚", - "\\bbthree" : "𝟛", - "\\bbfour" : "𝟜", - "\\bbfive" : "𝟝", - "\\bbsix" : "𝟞", - "\\bbseven" : "𝟟", - "\\bbeight" : "𝟠", - "\\bbnine" : "𝟡", - "\\sanszero" : "𝟢", - "\\sansone" : "𝟣", - "\\sanstwo" : "𝟤", - "\\sansthree" : "𝟥", - "\\sansfour" : "𝟦", - "\\sansfive" : "𝟧", - "\\sanssix" : "𝟨", - "\\sansseven" : "𝟩", - "\\sanseight" : "𝟪", - "\\sansnine" : "𝟫", - "\\bsanszero" : "𝟬", - "\\bsansone" : "𝟭", - "\\bsanstwo" : "𝟮", - "\\bsansthree" : "𝟯", - "\\bsansfour" : "𝟰", - "\\bsansfive" : "𝟱", - "\\bsanssix" : "𝟲", - "\\bsansseven" : "𝟳", - "\\bsanseight" : "𝟴", - "\\bsansnine" : "𝟵", - "\\ttzero" : "𝟶", - "\\ttone" : "𝟷", - "\\tttwo" : "𝟸", - "\\ttthree" : "𝟹", - "\\ttfour" : "𝟺", - "\\ttfive" : "𝟻", - "\\ttsix" : "𝟼", - "\\ttseven" : "𝟽", - "\\tteight" : "𝟾", - "\\ttnine" : "𝟿", - "\\underbar" : "̲", - "\\underleftrightarrow" : "͍", -} - - -reverse_latex_symbol = { v:k for k,v in latex_symbols.items()} diff --git a/contrib/python/ipython/py3/IPython/core/logger.py b/contrib/python/ipython/py3/IPython/core/logger.py deleted file mode 100644 index e3cb233cfa..0000000000 --- a/contrib/python/ipython/py3/IPython/core/logger.py +++ /dev/null @@ -1,218 +0,0 @@ -"""Logger class for IPython's logging facilities. -""" - -#***************************************************************************** -# Copyright (C) 2001 Janko Hauser <jhauser@zscout.de> and -# Copyright (C) 2001-2006 Fernando Perez <fperez@colorado.edu> -# -# Distributed under the terms of the BSD License. The full license is in -# the file COPYING, distributed as part of this software. -#***************************************************************************** - -#**************************************************************************** -# Modules and globals - -# Python standard modules -import glob -import io -import os -import time - - -#**************************************************************************** -# FIXME: This class isn't a mixin anymore, but it still needs attributes from -# ipython and does input cache management. Finish cleanup later... - -class Logger(object): - """A Logfile class with different policies for file creation""" - - def __init__(self, home_dir, logfname='Logger.log', loghead=u'', - logmode='over'): - - # this is the full ipython instance, we need some attributes from it - # which won't exist until later. What a mess, clean up later... - self.home_dir = home_dir - - self.logfname = logfname - self.loghead = loghead - self.logmode = logmode - self.logfile = None - - # Whether to log raw or processed input - self.log_raw_input = False - - # whether to also log output - self.log_output = False - - # whether to put timestamps before each log entry - self.timestamp = False - - # activity control flags - self.log_active = False - - # logmode is a validated property - def _set_mode(self,mode): - if mode not in ['append','backup','global','over','rotate']: - raise ValueError('invalid log mode %s given' % mode) - self._logmode = mode - - def _get_mode(self): - return self._logmode - - logmode = property(_get_mode,_set_mode) - - def logstart(self, logfname=None, loghead=None, logmode=None, - log_output=False, timestamp=False, log_raw_input=False): - """Generate a new log-file with a default header. - - Raises RuntimeError if the log has already been started""" - - if self.logfile is not None: - raise RuntimeError('Log file is already active: %s' % - self.logfname) - - # The parameters can override constructor defaults - if logfname is not None: self.logfname = logfname - if loghead is not None: self.loghead = loghead - if logmode is not None: self.logmode = logmode - - # Parameters not part of the constructor - self.timestamp = timestamp - self.log_output = log_output - self.log_raw_input = log_raw_input - - # init depending on the log mode requested - isfile = os.path.isfile - logmode = self.logmode - - if logmode == 'append': - self.logfile = io.open(self.logfname, 'a', encoding='utf-8') - - elif logmode == 'backup': - if isfile(self.logfname): - backup_logname = self.logfname+'~' - # Manually remove any old backup, since os.rename may fail - # under Windows. - if isfile(backup_logname): - os.remove(backup_logname) - os.rename(self.logfname,backup_logname) - self.logfile = io.open(self.logfname, 'w', encoding='utf-8') - - elif logmode == 'global': - self.logfname = os.path.join(self.home_dir,self.logfname) - self.logfile = io.open(self.logfname, 'a', encoding='utf-8') - - elif logmode == 'over': - if isfile(self.logfname): - os.remove(self.logfname) - self.logfile = io.open(self.logfname,'w', encoding='utf-8') - - elif logmode == 'rotate': - if isfile(self.logfname): - if isfile(self.logfname+'.001~'): - old = glob.glob(self.logfname+'.*~') - old.sort() - old.reverse() - for f in old: - root, ext = os.path.splitext(f) - num = int(ext[1:-1])+1 - os.rename(f, root+'.'+repr(num).zfill(3)+'~') - os.rename(self.logfname, self.logfname+'.001~') - self.logfile = io.open(self.logfname, 'w', encoding='utf-8') - - if logmode != 'append': - self.logfile.write(self.loghead) - - self.logfile.flush() - self.log_active = True - - def switch_log(self,val): - """Switch logging on/off. val should be ONLY a boolean.""" - - if val not in [False,True,0,1]: - raise ValueError('Call switch_log ONLY with a boolean argument, ' - 'not with: %s' % val) - - label = {0:'OFF',1:'ON',False:'OFF',True:'ON'} - - if self.logfile is None: - print(""" -Logging hasn't been started yet (use logstart for that). - -%logon/%logoff are for temporarily starting and stopping logging for a logfile -which already exists. But you must first start the logging process with -%logstart (optionally giving a logfile name).""") - - else: - if self.log_active == val: - print('Logging is already',label[val]) - else: - print('Switching logging',label[val]) - self.log_active = not self.log_active - self.log_active_out = self.log_active - - def logstate(self): - """Print a status message about the logger.""" - if self.logfile is None: - print('Logging has not been activated.') - else: - state = self.log_active and 'active' or 'temporarily suspended' - print('Filename :', self.logfname) - print('Mode :', self.logmode) - print('Output logging :', self.log_output) - print('Raw input log :', self.log_raw_input) - print('Timestamping :', self.timestamp) - print('State :', state) - - def log(self, line_mod, line_ori): - """Write the sources to a log. - - Inputs: - - - line_mod: possibly modified input, such as the transformations made - by input prefilters or input handlers of various kinds. This should - always be valid Python. - - - line_ori: unmodified input line from the user. This is not - necessarily valid Python. - """ - - # Write the log line, but decide which one according to the - # log_raw_input flag, set when the log is started. - if self.log_raw_input: - self.log_write(line_ori) - else: - self.log_write(line_mod) - - def log_write(self, data, kind='input'): - """Write data to the log file, if active""" - - #print 'data: %r' % data # dbg - if self.log_active and data: - write = self.logfile.write - if kind=='input': - if self.timestamp: - write(time.strftime('# %a, %d %b %Y %H:%M:%S\n', time.localtime())) - write(data) - elif kind=='output' and self.log_output: - odata = u'\n'.join([u'#[Out]# %s' % s - for s in data.splitlines()]) - write(u'%s\n' % odata) - self.logfile.flush() - - def logstop(self): - """Fully stop logging and close log file. - - In order to start logging again, a new logstart() call needs to be - made, possibly (though not necessarily) with a new filename, mode and - other options.""" - - if self.logfile is not None: - self.logfile.close() - self.logfile = None - else: - print("Logging hadn't been started.") - self.log_active = False - - # For backwards compatibility, in case anyone was using this. - close_log = logstop diff --git a/contrib/python/ipython/py3/IPython/core/macro.py b/contrib/python/ipython/py3/IPython/core/macro.py deleted file mode 100644 index ce86898cac..0000000000 --- a/contrib/python/ipython/py3/IPython/core/macro.py +++ /dev/null @@ -1,53 +0,0 @@ -"""Support for interactive macros in IPython""" - -#***************************************************************************** -# Copyright (C) 2001-2005 Fernando Perez <fperez@colorado.edu> -# -# Distributed under the terms of the BSD License. The full license is in -# the file COPYING, distributed as part of this software. -#***************************************************************************** - -import re - -from IPython.utils.encoding import DEFAULT_ENCODING - -coding_declaration = re.compile(r"#\s*coding[:=]\s*([-\w.]+)") - -class Macro(object): - """Simple class to store the value of macros as strings. - - Macro is just a callable that executes a string of IPython - input when called. - """ - - def __init__(self,code): - """store the macro value, as a single string which can be executed""" - lines = [] - enc = None - for line in code.splitlines(): - coding_match = coding_declaration.match(line) - if coding_match: - enc = coding_match.group(1) - else: - lines.append(line) - code = "\n".join(lines) - if isinstance(code, bytes): - code = code.decode(enc or DEFAULT_ENCODING) - self.value = code + '\n' - - def __str__(self): - return self.value - - def __repr__(self): - return 'IPython.macro.Macro(%s)' % repr(self.value) - - def __getstate__(self): - """ needed for safe pickling via %store """ - return {'value': self.value} - - def __add__(self, other): - if isinstance(other, Macro): - return Macro(self.value + other.value) - elif isinstance(other, str): - return Macro(self.value + other) - raise TypeError diff --git a/contrib/python/ipython/py3/IPython/core/magic.py b/contrib/python/ipython/py3/IPython/core/magic.py deleted file mode 100644 index cedba61937..0000000000 --- a/contrib/python/ipython/py3/IPython/core/magic.py +++ /dev/null @@ -1,746 +0,0 @@ -# encoding: utf-8 -"""Magic functions for InteractiveShell. -""" - -#----------------------------------------------------------------------------- -# Copyright (C) 2001 Janko Hauser <jhauser@zscout.de> and -# Copyright (C) 2001 Fernando Perez <fperez@colorado.edu> -# Copyright (C) 2008 The IPython Development Team - -# Distributed under the terms of the BSD License. The full license is in -# the file COPYING, distributed as part of this software. -#----------------------------------------------------------------------------- - -import os -import re -import sys -from getopt import getopt, GetoptError - -from traitlets.config.configurable import Configurable -from . import oinspect -from .error import UsageError -from .inputtransformer2 import ESC_MAGIC, ESC_MAGIC2 -from ..utils.ipstruct import Struct -from ..utils.process import arg_split -from ..utils.text import dedent -from traitlets import Bool, Dict, Instance, observe -from logging import error - -#----------------------------------------------------------------------------- -# Globals -#----------------------------------------------------------------------------- - -# A dict we'll use for each class that has magics, used as temporary storage to -# pass information between the @line/cell_magic method decorators and the -# @magics_class class decorator, because the method decorators have no -# access to the class when they run. See for more details: -# http://stackoverflow.com/questions/2366713/can-a-python-decorator-of-an-instance-method-access-the-class - -magics = dict(line={}, cell={}) - -magic_kinds = ('line', 'cell') -magic_spec = ('line', 'cell', 'line_cell') -magic_escapes = dict(line=ESC_MAGIC, cell=ESC_MAGIC2) - -#----------------------------------------------------------------------------- -# Utility classes and functions -#----------------------------------------------------------------------------- - -class Bunch: pass - - -def on_off(tag): - """Return an ON/OFF string for a 1/0 input. Simple utility function.""" - return ['OFF','ON'][tag] - - -def compress_dhist(dh): - """Compress a directory history into a new one with at most 20 entries. - - Return a new list made from the first and last 10 elements of dhist after - removal of duplicates. - """ - head, tail = dh[:-10], dh[-10:] - - newhead = [] - done = set() - for h in head: - if h in done: - continue - newhead.append(h) - done.add(h) - - return newhead + tail - - -def needs_local_scope(func): - """Decorator to mark magic functions which need to local scope to run.""" - func.needs_local_scope = True - return func - -#----------------------------------------------------------------------------- -# Class and method decorators for registering magics -#----------------------------------------------------------------------------- - -def magics_class(cls): - """Class decorator for all subclasses of the main Magics class. - - Any class that subclasses Magics *must* also apply this decorator, to - ensure that all the methods that have been decorated as line/cell magics - get correctly registered in the class instance. This is necessary because - when method decorators run, the class does not exist yet, so they - temporarily store their information into a module global. Application of - this class decorator copies that global data to the class instance and - clears the global. - - Obviously, this mechanism is not thread-safe, which means that the - *creation* of subclasses of Magic should only be done in a single-thread - context. Instantiation of the classes has no restrictions. Given that - these classes are typically created at IPython startup time and before user - application code becomes active, in practice this should not pose any - problems. - """ - cls.registered = True - cls.magics = dict(line = magics['line'], - cell = magics['cell']) - magics['line'] = {} - magics['cell'] = {} - return cls - - -def record_magic(dct, magic_kind, magic_name, func): - """Utility function to store a function as a magic of a specific kind. - - Parameters - ---------- - dct : dict - A dictionary with 'line' and 'cell' subdicts. - magic_kind : str - Kind of magic to be stored. - magic_name : str - Key to store the magic as. - func : function - Callable object to store. - """ - if magic_kind == 'line_cell': - dct['line'][magic_name] = dct['cell'][magic_name] = func - else: - dct[magic_kind][magic_name] = func - - -def validate_type(magic_kind): - """Ensure that the given magic_kind is valid. - - Check that the given magic_kind is one of the accepted spec types (stored - in the global `magic_spec`), raise ValueError otherwise. - """ - if magic_kind not in magic_spec: - raise ValueError('magic_kind must be one of %s, %s given' % - magic_kinds, magic_kind) - - -# The docstrings for the decorator below will be fairly similar for the two -# types (method and function), so we generate them here once and reuse the -# templates below. -_docstring_template = \ -"""Decorate the given {0} as {1} magic. - -The decorator can be used with or without arguments, as follows. - -i) without arguments: it will create a {1} magic named as the {0} being -decorated:: - - @deco - def foo(...) - -will create a {1} magic named `foo`. - -ii) with one string argument: which will be used as the actual name of the -resulting magic:: - - @deco('bar') - def foo(...) - -will create a {1} magic named `bar`. - -To register a class magic use ``Interactiveshell.register_magic(class or instance)``. -""" - -# These two are decorator factories. While they are conceptually very similar, -# there are enough differences in the details that it's simpler to have them -# written as completely standalone functions rather than trying to share code -# and make a single one with convoluted logic. - -def _method_magic_marker(magic_kind): - """Decorator factory for methods in Magics subclasses. - """ - - validate_type(magic_kind) - - # This is a closure to capture the magic_kind. We could also use a class, - # but it's overkill for just that one bit of state. - def magic_deco(arg): - if callable(arg): - # "Naked" decorator call (just @foo, no args) - func = arg - name = func.__name__ - retval = arg - record_magic(magics, magic_kind, name, name) - elif isinstance(arg, str): - # Decorator called with arguments (@foo('bar')) - name = arg - def mark(func, *a, **kw): - record_magic(magics, magic_kind, name, func.__name__) - return func - retval = mark - else: - raise TypeError("Decorator can only be called with " - "string or function") - return retval - - # Ensure the resulting decorator has a usable docstring - magic_deco.__doc__ = _docstring_template.format('method', magic_kind) - return magic_deco - - -def _function_magic_marker(magic_kind): - """Decorator factory for standalone functions. - """ - validate_type(magic_kind) - - # This is a closure to capture the magic_kind. We could also use a class, - # but it's overkill for just that one bit of state. - def magic_deco(arg): - # Find get_ipython() in the caller's namespace - caller = sys._getframe(1) - for ns in ['f_locals', 'f_globals', 'f_builtins']: - get_ipython = getattr(caller, ns).get('get_ipython') - if get_ipython is not None: - break - else: - raise NameError('Decorator can only run in context where ' - '`get_ipython` exists') - - ip = get_ipython() - - if callable(arg): - # "Naked" decorator call (just @foo, no args) - func = arg - name = func.__name__ - ip.register_magic_function(func, magic_kind, name) - retval = arg - elif isinstance(arg, str): - # Decorator called with arguments (@foo('bar')) - name = arg - def mark(func, *a, **kw): - ip.register_magic_function(func, magic_kind, name) - return func - retval = mark - else: - raise TypeError("Decorator can only be called with " - "string or function") - return retval - - # Ensure the resulting decorator has a usable docstring - ds = _docstring_template.format('function', magic_kind) - - ds += dedent(""" - Note: this decorator can only be used in a context where IPython is already - active, so that the `get_ipython()` call succeeds. You can therefore use - it in your startup files loaded after IPython initializes, but *not* in the - IPython configuration file itself, which is executed before IPython is - fully up and running. Any file located in the `startup` subdirectory of - your configuration profile will be OK in this sense. - """) - - magic_deco.__doc__ = ds - return magic_deco - - -MAGIC_NO_VAR_EXPAND_ATTR = '_ipython_magic_no_var_expand' - - -def no_var_expand(magic_func): - """Mark a magic function as not needing variable expansion - - By default, IPython interprets `{a}` or `$a` in the line passed to magics - as variables that should be interpolated from the interactive namespace - before passing the line to the magic function. - This is not always desirable, e.g. when the magic executes Python code - (%timeit, %time, etc.). - Decorate magics with `@no_var_expand` to opt-out of variable expansion. - - .. versionadded:: 7.3 - """ - setattr(magic_func, MAGIC_NO_VAR_EXPAND_ATTR, True) - return magic_func - - -# Create the actual decorators for public use - -# These three are used to decorate methods in class definitions -line_magic = _method_magic_marker('line') -cell_magic = _method_magic_marker('cell') -line_cell_magic = _method_magic_marker('line_cell') - -# These three decorate standalone functions and perform the decoration -# immediately. They can only run where get_ipython() works -register_line_magic = _function_magic_marker('line') -register_cell_magic = _function_magic_marker('cell') -register_line_cell_magic = _function_magic_marker('line_cell') - -#----------------------------------------------------------------------------- -# Core Magic classes -#----------------------------------------------------------------------------- - -class MagicsManager(Configurable): - """Object that handles all magic-related functionality for IPython. - """ - # Non-configurable class attributes - - # A two-level dict, first keyed by magic type, then by magic function, and - # holding the actual callable object as value. This is the dict used for - # magic function dispatch - magics = Dict() - lazy_magics = Dict( - help=""" - Mapping from magic names to modules to load. - - This can be used in IPython/IPykernel configuration to declare lazy magics - that will only be imported/registered on first use. - - For example:: - - c.MagicsManager.lazy_magics = { - "my_magic": "slow.to.import", - "my_other_magic": "also.slow", - } - - On first invocation of `%my_magic`, `%%my_magic`, `%%my_other_magic` or - `%%my_other_magic`, the corresponding module will be loaded as an ipython - extensions as if you had previously done `%load_ext ipython`. - - Magics names should be without percent(s) as magics can be both cell - and line magics. - - Lazy loading happen relatively late in execution process, and - complex extensions that manipulate Python/IPython internal state or global state - might not support lazy loading. - """ - ).tag( - config=True, - ) - - # A registry of the original objects that we've been given holding magics. - registry = Dict() - - 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_status = [ - 'Automagic is OFF, % prefix IS needed for line magics.', - 'Automagic is ON, % prefix IS NOT needed for line magics.'] - - user_magics = Instance('IPython.core.magics.UserMagics', allow_none=True) - - def __init__(self, shell=None, config=None, user_magics=None, **traits): - - super(MagicsManager, self).__init__(shell=shell, config=config, - user_magics=user_magics, **traits) - self.magics = dict(line={}, cell={}) - # Let's add the user_magics to the registry for uniformity, so *all* - # registered magic containers can be found there. - self.registry[user_magics.__class__.__name__] = user_magics - - def auto_status(self): - """Return descriptive string with automagic status.""" - return self._auto_status[self.auto_magic] - - def lsmagic(self): - """Return a dict of currently available magic functions. - - The return dict has the keys 'line' and 'cell', corresponding to the - two types of magics we support. Each value is a list of names. - """ - return self.magics - - def lsmagic_docs(self, brief=False, missing=''): - """Return dict of documentation of magic functions. - - The return dict has the keys 'line' and 'cell', corresponding to the - two types of magics we support. Each value is a dict keyed by magic - name whose value is the function docstring. If a docstring is - unavailable, the value of `missing` is used instead. - - If brief is True, only the first line of each docstring will be returned. - """ - docs = {} - for m_type in self.magics: - m_docs = {} - for m_name, m_func in self.magics[m_type].items(): - if m_func.__doc__: - if brief: - m_docs[m_name] = m_func.__doc__.split('\n', 1)[0] - else: - m_docs[m_name] = m_func.__doc__.rstrip() - else: - m_docs[m_name] = missing - docs[m_type] = m_docs - return docs - - def register_lazy(self, name: str, fully_qualified_name: str): - """ - Lazily register a magic via an extension. - - - Parameters - ---------- - name : str - Name of the magic you wish to register. - fully_qualified_name : - Fully qualified name of the module/submodule that should be loaded - as an extensions when the magic is first called. - It is assumed that loading this extensions will register the given - magic. - """ - - self.lazy_magics[name] = fully_qualified_name - - def register(self, *magic_objects): - """Register one or more instances of Magics. - - Take one or more classes or instances of classes that subclass the main - `core.Magic` class, and register them with IPython to use the magic - functions they provide. The registration process will then ensure that - any methods that have decorated to provide line and/or cell magics will - be recognized with the `%x`/`%%x` syntax as a line/cell magic - respectively. - - If classes are given, they will be instantiated with the default - constructor. If your classes need a custom constructor, you should - instanitate them first and pass the instance. - - The provided arguments can be an arbitrary mix of classes and instances. - - Parameters - ---------- - *magic_objects : one or more classes or instances - """ - # Start by validating them to ensure they have all had their magic - # methods registered at the instance level - for m in magic_objects: - if not m.registered: - raise ValueError("Class of magics %r was constructed without " - "the @register_magics class decorator") - if isinstance(m, type): - # If we're given an uninstantiated class - m = m(shell=self.shell) - - # Now that we have an instance, we can register it and update the - # table of callables - self.registry[m.__class__.__name__] = m - for mtype in magic_kinds: - self.magics[mtype].update(m.magics[mtype]) - - def register_function(self, func, magic_kind='line', magic_name=None): - """Expose a standalone function as magic function for IPython. - - This will create an IPython magic (line, cell or both) from a - standalone function. The functions should have the following - signatures: - - * For line magics: `def f(line)` - * For cell magics: `def f(line, cell)` - * For a function that does both: `def f(line, cell=None)` - - In the latter case, the function will be called with `cell==None` when - invoked as `%f`, and with cell as a string when invoked as `%%f`. - - Parameters - ---------- - func : callable - Function to be registered as a magic. - magic_kind : str - Kind of magic, one of 'line', 'cell' or 'line_cell' - magic_name : optional str - If given, the name the magic will have in the IPython namespace. By - default, the name of the function itself is used. - """ - - # Create the new method in the user_magics and register it in the - # global table - validate_type(magic_kind) - magic_name = func.__name__ if magic_name is None else magic_name - setattr(self.user_magics, magic_name, func) - record_magic(self.magics, magic_kind, magic_name, func) - - def register_alias(self, alias_name, magic_name, magic_kind='line', magic_params=None): - """Register an alias to a magic function. - - The alias is an instance of :class:`MagicAlias`, which holds the - name and kind of the magic it should call. Binding is done at - call time, so if the underlying magic function is changed the alias - will call the new function. - - Parameters - ---------- - alias_name : str - The name of the magic to be registered. - magic_name : str - The name of an existing magic. - magic_kind : str - Kind of magic, one of 'line' or 'cell' - """ - - # `validate_type` is too permissive, as it allows 'line_cell' - # which we do not handle. - if magic_kind not in magic_kinds: - raise ValueError('magic_kind must be one of %s, %s given' % - magic_kinds, magic_kind) - - alias = MagicAlias(self.shell, magic_name, magic_kind, magic_params) - setattr(self.user_magics, alias_name, alias) - record_magic(self.magics, magic_kind, alias_name, alias) - -# Key base class that provides the central functionality for magics. - - -class Magics(Configurable): - """Base class for implementing magic functions. - - Shell functions which can be reached as %function_name. All magic - functions should accept a string, which they can parse for their own - needs. This can make some functions easier to type, eg `%cd ../` - vs. `%cd("../")` - - Classes providing magic functions need to subclass this class, and they - MUST: - - - Use the method decorators `@line_magic` and `@cell_magic` to decorate - individual methods as magic functions, AND - - - Use the class decorator `@magics_class` to ensure that the magic - methods are properly registered at the instance level upon instance - initialization. - - See :mod:`magic_functions` for examples of actual implementation classes. - """ - # Dict holding all command-line options for each magic. - options_table = None - # Dict for the mapping of magic names to methods, set by class decorator - magics = None - # Flag to check that the class decorator was properly applied - registered = False - # Instance of IPython shell - shell = None - - def __init__(self, shell=None, **kwargs): - if not(self.__class__.registered): - raise ValueError('Magics subclass without registration - ' - 'did you forget to apply @magics_class?') - if shell is not None: - if hasattr(shell, 'configurables'): - shell.configurables.append(self) - if hasattr(shell, 'config'): - kwargs.setdefault('parent', shell) - - self.shell = shell - self.options_table = {} - # The method decorators are run when the instance doesn't exist yet, so - # they can only record the names of the methods they are supposed to - # grab. Only now, that the instance exists, can we create the proper - # mapping to bound methods. So we read the info off the original names - # table and replace each method name by the actual bound method. - # But we mustn't clobber the *class* mapping, in case of multiple instances. - class_magics = self.magics - self.magics = {} - for mtype in magic_kinds: - tab = self.magics[mtype] = {} - cls_tab = class_magics[mtype] - for magic_name, meth_name in cls_tab.items(): - if isinstance(meth_name, str): - # it's a method name, grab it - tab[magic_name] = getattr(self, meth_name) - else: - # it's the real thing - tab[magic_name] = meth_name - # Configurable **needs** to be initiated at the end or the config - # magics get screwed up. - super(Magics, self).__init__(**kwargs) - - def arg_err(self,func): - """Print docstring if incorrect arguments were passed""" - print('Error in arguments:') - print(oinspect.getdoc(func)) - - def format_latex(self, strng): - """Format a string for latex inclusion.""" - - # Characters that need to be escaped for latex: - escape_re = re.compile(r'(%|_|\$|#|&)',re.MULTILINE) - # Magic command names as headers: - cmd_name_re = re.compile(r'^(%s.*?):' % ESC_MAGIC, - re.MULTILINE) - # Magic commands - cmd_re = re.compile(r'(?P<cmd>%s.+?\b)(?!\}\}:)' % ESC_MAGIC, - re.MULTILINE) - # Paragraph continue - par_re = re.compile(r'\\$',re.MULTILINE) - - # The "\n" symbol - newline_re = re.compile(r'\\n') - - # Now build the string for output: - #strng = cmd_name_re.sub(r'\n\\texttt{\\textsl{\\large \1}}:',strng) - strng = cmd_name_re.sub(r'\n\\bigskip\n\\texttt{\\textbf{ \1}}:', - strng) - strng = cmd_re.sub(r'\\texttt{\g<cmd>}',strng) - strng = par_re.sub(r'\\\\',strng) - strng = escape_re.sub(r'\\\1',strng) - strng = newline_re.sub(r'\\textbackslash{}n',strng) - return strng - - def parse_options(self, arg_str, opt_str, *long_opts, **kw): - """Parse options passed to an argument string. - - The interface is similar to that of :func:`getopt.getopt`, but it - returns a :class:`~IPython.utils.struct.Struct` with the options as keys - and the stripped argument string still as a string. - - arg_str is quoted as a true sys.argv vector by using shlex.split. - This allows us to easily expand variables, glob files, quote - arguments, etc. - - Parameters - ---------- - arg_str : str - The arguments to parse. - opt_str : str - The options specification. - mode : str, default 'string' - If given as 'list', the argument string is returned as a list (split - on whitespace) instead of a string. - list_all : bool, default False - Put all option values in lists. Normally only options - appearing more than once are put in a list. - posix : bool, default True - Whether to split the input line in POSIX mode or not, as per the - conventions outlined in the :mod:`shlex` module from the standard - library. - """ - - # inject default options at the beginning of the input line - caller = sys._getframe(1).f_code.co_name - arg_str = '%s %s' % (self.options_table.get(caller,''),arg_str) - - mode = kw.get('mode','string') - if mode not in ['string','list']: - raise ValueError('incorrect mode given: %s' % mode) - # Get options - list_all = kw.get('list_all',0) - posix = kw.get('posix', os.name == 'posix') - strict = kw.get('strict', True) - - preserve_non_opts = kw.get("preserve_non_opts", False) - remainder_arg_str = arg_str - - # Check if we have more than one argument to warrant extra processing: - odict = {} # Dictionary with options - args = arg_str.split() - if len(args) >= 1: - # If the list of inputs only has 0 or 1 thing in it, there's no - # need to look for options - argv = arg_split(arg_str, posix, strict) - # Do regular option processing - try: - opts,args = getopt(argv, opt_str, long_opts) - except GetoptError as e: - raise UsageError( - '%s ( allowed: "%s" %s)' % (e.msg, opt_str, " ".join(long_opts)) - ) from e - for o, a in opts: - if mode == "string" and preserve_non_opts: - # remove option-parts from the original args-string and preserve remaining-part. - # This relies on the arg_split(...) and getopt(...)'s impl spec, that the parsed options are - # returned in the original order. - remainder_arg_str = remainder_arg_str.replace(o, "", 1).replace( - a, "", 1 - ) - if o.startswith("--"): - o = o[2:] - else: - o = o[1:] - try: - odict[o].append(a) - except AttributeError: - odict[o] = [odict[o],a] - except KeyError: - if list_all: - odict[o] = [a] - else: - odict[o] = a - - # Prepare opts,args for return - opts = Struct(odict) - if mode == 'string': - if preserve_non_opts: - args = remainder_arg_str.lstrip() - else: - args = " ".join(args) - - return opts,args - - def default_option(self, fn, optstr): - """Make an entry in the options_table for fn, with value optstr""" - - if fn not in self.lsmagic(): - error("%s is not a magic function" % fn) - self.options_table[fn] = optstr - - -class MagicAlias(object): - """An alias to another magic function. - - An alias is determined by its magic name and magic kind. Lookup - is done at call time, so if the underlying magic changes the alias - will call the new function. - - Use the :meth:`MagicsManager.register_alias` method or the - `%alias_magic` magic function to create and register a new alias. - """ - def __init__(self, shell, magic_name, magic_kind, magic_params=None): - self.shell = shell - self.magic_name = magic_name - self.magic_params = magic_params - self.magic_kind = magic_kind - - self.pretty_target = '%s%s' % (magic_escapes[self.magic_kind], self.magic_name) - self.__doc__ = "Alias for `%s`." % self.pretty_target - - self._in_call = False - - def __call__(self, *args, **kwargs): - """Call the magic alias.""" - fn = self.shell.find_magic(self.magic_name, self.magic_kind) - if fn is None: - raise UsageError("Magic `%s` not found." % self.pretty_target) - - # Protect against infinite recursion. - if self._in_call: - raise UsageError("Infinite recursion detected; " - "magic aliases cannot call themselves.") - self._in_call = True - try: - if self.magic_params: - args_list = list(args) - args_list[0] = self.magic_params + " " + args[0] - args = tuple(args_list) - return fn(*args, **kwargs) - finally: - self._in_call = False diff --git a/contrib/python/ipython/py3/IPython/core/magic_arguments.py b/contrib/python/ipython/py3/IPython/core/magic_arguments.py deleted file mode 100644 index 568abd82ae..0000000000 --- a/contrib/python/ipython/py3/IPython/core/magic_arguments.py +++ /dev/null @@ -1,310 +0,0 @@ -''' A decorator-based method of constructing IPython magics with `argparse` -option handling. - -New magic functions can be defined like so:: - - from IPython.core.magic_arguments import (argument, magic_arguments, - parse_argstring) - - @magic_arguments() - @argument('-o', '--option', help='An optional argument.') - @argument('arg', type=int, help='An integer positional argument.') - def magic_cool(self, arg): - """ A really cool magic command. - - """ - args = parse_argstring(magic_cool, arg) - ... - -The `@magic_arguments` decorator marks the function as having argparse arguments. -The `@argument` decorator adds an argument using the same syntax as argparse's -`add_argument()` method. More sophisticated uses may also require the -`@argument_group` or `@kwds` decorator to customize the formatting and the -parsing. - -Help text for the magic is automatically generated from the docstring and the -arguments:: - - In[1]: %cool? - %cool [-o OPTION] arg - - A really cool magic command. - - positional arguments: - arg An integer positional argument. - - optional arguments: - -o OPTION, --option OPTION - An optional argument. - -Here is an elaborated example that uses default parameters in `argument` and calls the `args` in the cell magic:: - - from IPython.core.magic import register_cell_magic - from IPython.core.magic_arguments import (argument, magic_arguments, - parse_argstring) - - - @magic_arguments() - @argument( - "--option", - "-o", - help=("Add an option here"), - ) - @argument( - "--style", - "-s", - default="foo", - help=("Add some style arguments"), - ) - @register_cell_magic - def my_cell_magic(line, cell): - args = parse_argstring(my_cell_magic, line) - print(f"{args.option=}") - print(f"{args.style=}") - print(f"{cell=}") - -In a jupyter notebook, this cell magic can be executed like this:: - - %%my_cell_magic -o Hello - print("bar") - i = 42 - -Inheritance diagram: - -.. inheritance-diagram:: IPython.core.magic_arguments - :parts: 3 - -''' -#----------------------------------------------------------------------------- -# Copyright (C) 2010-2011, IPython Development Team. -# -# Distributed under the terms of the Modified BSD License. -# -# The full license is in the file COPYING.txt, distributed with this software. -#----------------------------------------------------------------------------- -import argparse -import re - -# Our own imports -from IPython.core.error import UsageError -from IPython.utils.decorators import undoc -from IPython.utils.process import arg_split -from IPython.utils.text import dedent - -NAME_RE = re.compile(r"[a-zA-Z][a-zA-Z0-9_-]*$") - -@undoc -class MagicHelpFormatter(argparse.RawDescriptionHelpFormatter): - """A HelpFormatter with a couple of changes to meet our needs. - """ - # Modified to dedent text. - def _fill_text(self, text, width, indent): - return argparse.RawDescriptionHelpFormatter._fill_text(self, dedent(text), width, indent) - - # Modified to wrap argument placeholders in <> where necessary. - def _format_action_invocation(self, action): - if not action.option_strings: - metavar, = self._metavar_formatter(action, action.dest)(1) - return metavar - - else: - parts = [] - - # if the Optional doesn't take a value, format is: - # -s, --long - if action.nargs == 0: - parts.extend(action.option_strings) - - # if the Optional takes a value, format is: - # -s ARGS, --long ARGS - else: - default = action.dest.upper() - args_string = self._format_args(action, default) - # IPYTHON MODIFICATION: If args_string is not a plain name, wrap - # it in <> so it's valid RST. - if not NAME_RE.match(args_string): - args_string = "<%s>" % args_string - for option_string in action.option_strings: - parts.append('%s %s' % (option_string, args_string)) - - return ', '.join(parts) - - # Override the default prefix ('usage') to our % magic escape, - # in a code block. - def add_usage(self, usage, actions, groups, prefix="::\n\n %"): - super(MagicHelpFormatter, self).add_usage(usage, actions, groups, prefix) - -class MagicArgumentParser(argparse.ArgumentParser): - """ An ArgumentParser tweaked for use by IPython magics. - """ - def __init__(self, - prog=None, - usage=None, - description=None, - epilog=None, - parents=None, - formatter_class=MagicHelpFormatter, - prefix_chars='-', - argument_default=None, - conflict_handler='error', - add_help=False): - if parents is None: - parents = [] - super(MagicArgumentParser, self).__init__(prog=prog, usage=usage, - description=description, epilog=epilog, - parents=parents, formatter_class=formatter_class, - prefix_chars=prefix_chars, argument_default=argument_default, - conflict_handler=conflict_handler, add_help=add_help) - - def error(self, message): - """ Raise a catchable error instead of exiting. - """ - raise UsageError(message) - - def parse_argstring(self, argstring): - """ Split a string into an argument list and parse that argument list. - """ - argv = arg_split(argstring) - return self.parse_args(argv) - - -def construct_parser(magic_func): - """ Construct an argument parser using the function decorations. - """ - kwds = getattr(magic_func, 'argcmd_kwds', {}) - if 'description' not in kwds: - kwds['description'] = getattr(magic_func, '__doc__', None) - arg_name = real_name(magic_func) - parser = MagicArgumentParser(arg_name, **kwds) - # Reverse the list of decorators in order to apply them in the - # order in which they appear in the source. - group = None - for deco in magic_func.decorators[::-1]: - result = deco.add_to_parser(parser, group) - if result is not None: - group = result - - # Replace the magic function's docstring with the full help text. - magic_func.__doc__ = parser.format_help() - - return parser - - -def parse_argstring(magic_func, argstring): - """ Parse the string of arguments for the given magic function. - """ - return magic_func.parser.parse_argstring(argstring) - - -def real_name(magic_func): - """ Find the real name of the magic. - """ - magic_name = magic_func.__name__ - if magic_name.startswith('magic_'): - magic_name = magic_name[len('magic_'):] - return getattr(magic_func, 'argcmd_name', magic_name) - - -class ArgDecorator(object): - """ Base class for decorators to add ArgumentParser information to a method. - """ - - def __call__(self, func): - if not getattr(func, 'has_arguments', False): - func.has_arguments = True - func.decorators = [] - func.decorators.append(self) - return func - - def add_to_parser(self, parser, group): - """ Add this object's information to the parser, if necessary. - """ - pass - - -class magic_arguments(ArgDecorator): - """ Mark the magic as having argparse arguments and possibly adjust the - name. - """ - - def __init__(self, name=None): - self.name = name - - def __call__(self, func): - if not getattr(func, 'has_arguments', False): - func.has_arguments = True - func.decorators = [] - if self.name is not None: - func.argcmd_name = self.name - # This should be the first decorator in the list of decorators, thus the - # last to execute. Build the parser. - func.parser = construct_parser(func) - return func - - -class ArgMethodWrapper(ArgDecorator): - - """ - Base class to define a wrapper for ArgumentParser method. - - Child class must define either `_method_name` or `add_to_parser`. - - """ - - _method_name = None - - def __init__(self, *args, **kwds): - self.args = args - self.kwds = kwds - - def add_to_parser(self, parser, group): - """ Add this object's information to the parser. - """ - if group is not None: - parser = group - getattr(parser, self._method_name)(*self.args, **self.kwds) - return None - - -class argument(ArgMethodWrapper): - """ Store arguments and keywords to pass to add_argument(). - - Instances also serve to decorate command methods. - """ - _method_name = 'add_argument' - - -class defaults(ArgMethodWrapper): - """ Store arguments and keywords to pass to set_defaults(). - - Instances also serve to decorate command methods. - """ - _method_name = 'set_defaults' - - -class argument_group(ArgMethodWrapper): - """ Store arguments and keywords to pass to add_argument_group(). - - Instances also serve to decorate command methods. - """ - - def add_to_parser(self, parser, group): - """ Add this object's information to the parser. - """ - return parser.add_argument_group(*self.args, **self.kwds) - - -class kwds(ArgDecorator): - """ Provide other keywords to the sub-parser constructor. - """ - def __init__(self, **kwds): - self.kwds = kwds - - def __call__(self, func): - func = super(kwds, self).__call__(func) - func.argcmd_kwds = self.kwds - return func - - -__all__ = ['magic_arguments', 'argument', 'argument_group', 'kwds', - 'parse_argstring'] diff --git a/contrib/python/ipython/py3/IPython/core/magics/__init__.py b/contrib/python/ipython/py3/IPython/core/magics/__init__.py deleted file mode 100644 index a6c5f474c1..0000000000 --- a/contrib/python/ipython/py3/IPython/core/magics/__init__.py +++ /dev/null @@ -1,42 +0,0 @@ -"""Implementation of all the magic functions built into IPython. -""" -#----------------------------------------------------------------------------- -# Copyright (c) 2012 The IPython Development Team. -# -# Distributed under the terms of the Modified BSD License. -# -# The full license is in the file COPYING.txt, distributed with this software. -#----------------------------------------------------------------------------- - -#----------------------------------------------------------------------------- -# Imports -#----------------------------------------------------------------------------- - -from ..magic import Magics, magics_class -from .auto import AutoMagics -from .basic import BasicMagics, AsyncMagics -from .code import CodeMagics, MacroToEdit -from .config import ConfigMagics -from .display import DisplayMagics -from .execution import ExecutionMagics -from .extension import ExtensionMagics -from .history import HistoryMagics -from .logging import LoggingMagics -from .namespace import NamespaceMagics -from .osm import OSMagics -from .packaging import PackagingMagics -from .pylab import PylabMagics -from .script import ScriptMagics - -#----------------------------------------------------------------------------- -# Magic implementation classes -#----------------------------------------------------------------------------- - -@magics_class -class UserMagics(Magics): - """Placeholder for user-defined magics to be added at runtime. - - All magics are eventually merged into a single namespace at runtime, but we - use this class to isolate the magics defined dynamically by the user into - their own class. - """ diff --git a/contrib/python/ipython/py3/IPython/core/magics/auto.py b/contrib/python/ipython/py3/IPython/core/magics/auto.py deleted file mode 100644 index 56aa4f72eb..0000000000 --- a/contrib/python/ipython/py3/IPython/core/magics/auto.py +++ /dev/null @@ -1,144 +0,0 @@ -"""Implementation of magic functions that control various automatic behaviors. -""" -#----------------------------------------------------------------------------- -# Copyright (c) 2012 The IPython Development Team. -# -# Distributed under the terms of the Modified BSD License. -# -# The full license is in the file COPYING.txt, distributed with this software. -#----------------------------------------------------------------------------- - -#----------------------------------------------------------------------------- -# Imports -#----------------------------------------------------------------------------- - -# 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 - -#----------------------------------------------------------------------------- -# Magic implementation classes -#----------------------------------------------------------------------------- - -@magics_class -class AutoMagics(Magics): - """Magics that control various autoX behaviors.""" - - def __init__(self, shell): - super(AutoMagics, self).__init__(shell) - # namespace for holding state we may need - self._magic_state = Bunch() - - @line_magic - def automagic(self, parameter_s=''): - """Make magic functions callable without having to type the initial %. - - Without arguments toggles on/off (when off, you must call it as - %automagic, of course). With arguments it sets the value, and you can - use any of (case insensitive): - - - on, 1, True: to activate - - - off, 0, False: to deactivate. - - Note that magic functions have lowest priority, so if there's a - variable whose name collides with that of a magic fn, automagic won't - work for that function (you get the variable instead). However, if you - delete the variable (del var), the previously shadowed magic function - becomes visible to automagic again.""" - - arg = parameter_s.lower() - mman = self.shell.magics_manager - if arg in ('on', '1', 'true'): - val = True - elif arg in ('off', '0', 'false'): - val = False - else: - val = not mman.auto_magic - mman.auto_magic = val - print('\n' + self.shell.magics_manager.auto_status()) - - @skip_doctest - @line_magic - def autocall(self, parameter_s=''): - """Make functions callable without having to type parentheses. - - Usage: - - %autocall [mode] - - The mode can be one of: 0->Off, 1->Smart, 2->Full. If not given, the - value is toggled on and off (remembering the previous state). - - In more detail, these values mean: - - 0 -> fully disabled - - 1 -> active, but do not apply if there are no arguments on the line. - - In this mode, you get:: - - In [1]: callable - Out[1]: <built-in function callable> - - In [2]: callable 'hello' - ------> callable('hello') - Out[2]: False - - 2 -> Active always. Even if no arguments are present, the callable - object is called:: - - In [2]: float - ------> float() - Out[2]: 0.0 - - Note that even with autocall off, you can still use '/' at the start of - a line to treat the first argument on the command line as a function - and add parentheses to it:: - - In [8]: /str 43 - ------> str(43) - Out[8]: '43' - - # all-random (note for auto-testing) - """ - - valid_modes = { - 0: "Off", - 1: "Smart", - 2: "Full", - } - - def errorMessage() -> str: - error = "Valid modes: " - for k, v in valid_modes.items(): - error += str(k) + "->" + v + ", " - error = error[:-2] # remove tailing `, ` after last element - return error - - if parameter_s: - if not parameter_s in map(str, valid_modes.keys()): - error(errorMessage()) - return - arg = int(parameter_s) - else: - arg = 'toggle' - - if not arg in (*list(valid_modes.keys()), "toggle"): - error(errorMessage()) - return - - if arg in (valid_modes.keys()): - self.shell.autocall = arg - else: # toggle - if self.shell.autocall: - self._magic_state.autocall_save = self.shell.autocall - self.shell.autocall = 0 - else: - try: - self.shell.autocall = self._magic_state.autocall_save - except AttributeError: - self.shell.autocall = self._magic_state.autocall_save = 1 - - print("Automatic calling is:", list(valid_modes.values())[self.shell.autocall]) diff --git a/contrib/python/ipython/py3/IPython/core/magics/basic.py b/contrib/python/ipython/py3/IPython/core/magics/basic.py deleted file mode 100644 index c1f6945110..0000000000 --- a/contrib/python/ipython/py3/IPython/core/magics/basic.py +++ /dev/null @@ -1,659 +0,0 @@ -"""Implementation of basic magic functions.""" - - -import argparse -from logging import error -import io -import os -from pprint import pformat -import sys -from warnings import warn - -from traitlets.utils.importstring import import_item -from IPython.core import magic_arguments, page -from IPython.core.error import UsageError -from IPython.core.magic import Magics, magics_class, line_magic, magic_escapes -from IPython.utils.text import format_screen, dedent, indent -from IPython.testing.skipdoctest import skip_doctest -from IPython.utils.ipstruct import Struct - - -class MagicsDisplay(object): - def __init__(self, magics_manager, ignore=None): - self.ignore = ignore if ignore else [] - self.magics_manager = magics_manager - - def _lsmagic(self): - """The main implementation of the %lsmagic""" - mesc = magic_escapes['line'] - cesc = magic_escapes['cell'] - mman = self.magics_manager - magics = mman.lsmagic() - out = ['Available line magics:', - mesc + (' '+mesc).join(sorted([m for m,v in magics['line'].items() if (v not in self.ignore)])), - '', - 'Available cell magics:', - cesc + (' '+cesc).join(sorted([m for m,v in magics['cell'].items() if (v not in self.ignore)])), - '', - mman.auto_status()] - return '\n'.join(out) - - def _repr_pretty_(self, p, cycle): - p.text(self._lsmagic()) - - def __str__(self): - return self._lsmagic() - - def _jsonable(self): - """turn magics dict into jsonable dict of the same structure - - replaces object instances with their class names as strings - """ - magic_dict = {} - mman = self.magics_manager - magics = mman.lsmagic() - for key, subdict in magics.items(): - d = {} - magic_dict[key] = d - for name, obj in subdict.items(): - try: - classname = obj.__self__.__class__.__name__ - except AttributeError: - classname = 'Other' - - d[name] = classname - return magic_dict - - def _repr_json_(self): - return self._jsonable() - - -@magics_class -class BasicMagics(Magics): - """Magics that provide central IPython functionality. - - These are various magics that don't fit into specific categories but that - are all part of the base 'IPython experience'.""" - - @skip_doctest - @magic_arguments.magic_arguments() - @magic_arguments.argument( - '-l', '--line', action='store_true', - help="""Create a line magic alias.""" - ) - @magic_arguments.argument( - '-c', '--cell', action='store_true', - help="""Create a cell magic alias.""" - ) - @magic_arguments.argument( - 'name', - help="""Name of the magic to be created.""" - ) - @magic_arguments.argument( - 'target', - help="""Name of the existing line or cell magic.""" - ) - @magic_arguments.argument( - '-p', '--params', default=None, - help="""Parameters passed to the magic function.""" - ) - @line_magic - def alias_magic(self, line=''): - """Create an alias for an existing line or cell magic. - - Examples - -------- - :: - - In [1]: %alias_magic t timeit - Created `%t` as an alias for `%timeit`. - Created `%%t` as an alias for `%%timeit`. - - In [2]: %t -n1 pass - 1 loops, best of 3: 954 ns per loop - - In [3]: %%t -n1 - ...: pass - ...: - 1 loops, best of 3: 954 ns per loop - - In [4]: %alias_magic --cell whereami pwd - UsageError: Cell magic function `%%pwd` not found. - In [5]: %alias_magic --line whereami pwd - Created `%whereami` as an alias for `%pwd`. - - In [6]: %whereami - Out[6]: u'/home/testuser' - - In [7]: %alias_magic h history "-p -l 30" --line - Created `%h` as an alias for `%history -l 30`. - """ - - args = magic_arguments.parse_argstring(self.alias_magic, line) - shell = self.shell - mman = self.shell.magics_manager - escs = ''.join(magic_escapes.values()) - - target = args.target.lstrip(escs) - name = args.name.lstrip(escs) - - params = args.params - if (params and - ((params.startswith('"') and params.endswith('"')) - or (params.startswith("'") and params.endswith("'")))): - params = params[1:-1] - - # Find the requested magics. - m_line = shell.find_magic(target, 'line') - m_cell = shell.find_magic(target, 'cell') - if args.line and m_line is None: - raise UsageError('Line magic function `%s%s` not found.' % - (magic_escapes['line'], target)) - if args.cell and m_cell is None: - raise UsageError('Cell magic function `%s%s` not found.' % - (magic_escapes['cell'], target)) - - # If --line and --cell are not specified, default to the ones - # that are available. - if not args.line and not args.cell: - if not m_line and not m_cell: - raise UsageError( - 'No line or cell magic with name `%s` found.' % target - ) - args.line = bool(m_line) - args.cell = bool(m_cell) - - params_str = "" if params is None else " " + params - - if args.line: - mman.register_alias(name, target, 'line', params) - print('Created `%s%s` as an alias for `%s%s%s`.' % ( - magic_escapes['line'], name, - magic_escapes['line'], target, params_str)) - - if args.cell: - mman.register_alias(name, target, 'cell', params) - print('Created `%s%s` as an alias for `%s%s%s`.' % ( - magic_escapes['cell'], name, - magic_escapes['cell'], target, params_str)) - - @line_magic - def lsmagic(self, parameter_s=''): - """List currently available magic functions.""" - return MagicsDisplay(self.shell.magics_manager, ignore=[]) - - def _magic_docs(self, brief=False, rest=False): - """Return docstrings from magic functions.""" - mman = self.shell.magics_manager - docs = mman.lsmagic_docs(brief, missing='No documentation') - - if rest: - format_string = '**%s%s**::\n\n%s\n\n' - else: - format_string = '%s%s:\n%s\n' - - return ''.join( - [format_string % (magic_escapes['line'], fname, - indent(dedent(fndoc))) - for fname, fndoc in sorted(docs['line'].items())] - + - [format_string % (magic_escapes['cell'], fname, - indent(dedent(fndoc))) - for fname, fndoc in sorted(docs['cell'].items())] - ) - - @line_magic - def magic(self, parameter_s=''): - """Print information about the magic function system. - - Supported formats: -latex, -brief, -rest - """ - - mode = '' - try: - mode = parameter_s.split()[0][1:] - except IndexError: - pass - - brief = (mode == 'brief') - rest = (mode == 'rest') - magic_docs = self._magic_docs(brief, rest) - - if mode == 'latex': - print(self.format_latex(magic_docs)) - return - else: - magic_docs = format_screen(magic_docs) - - out = [""" -IPython's 'magic' functions -=========================== - -The magic function system provides a series of functions which allow you to -control the behavior of IPython itself, plus a lot of system-type -features. There are two kinds of magics, line-oriented and cell-oriented. - -Line magics are prefixed with the % character and work much like OS -command-line calls: they get as an argument the rest of the line, where -arguments are passed without parentheses or quotes. For example, this will -time the given statement:: - - %timeit range(1000) - -Cell magics are prefixed with a double %%, and they are functions that get as -an argument not only the rest of the line, but also the lines below it in a -separate argument. These magics are called with two arguments: the rest of the -call line and the body of the cell, consisting of the lines below the first. -For example:: - - %%timeit x = numpy.random.randn((100, 100)) - numpy.linalg.svd(x) - -will time the execution of the numpy svd routine, running the assignment of x -as part of the setup phase, which is not timed. - -In a line-oriented client (the terminal or Qt console IPython), starting a new -input with %% will automatically enter cell mode, and IPython will continue -reading input until a blank line is given. In the notebook, simply type the -whole cell as one entity, but keep in mind that the %% escape can only be at -the very start of the cell. - -NOTE: If you have 'automagic' enabled (via the command line option or with the -%automagic function), you don't need to type in the % explicitly for line -magics; cell magics always require an explicit '%%' escape. By default, -IPython ships with automagic on, so you should only rarely need the % escape. - -Example: typing '%cd mydir' (without the quotes) changes your working directory -to 'mydir', if it exists. - -For a list of the available magic functions, use %lsmagic. For a description -of any of them, type %magic_name?, e.g. '%cd?'. - -Currently the magic system has the following functions:""", - magic_docs, - "Summary of magic functions (from %slsmagic):" % magic_escapes['line'], - str(self.lsmagic()), - ] - page.page('\n'.join(out)) - - - @line_magic - def page(self, parameter_s=''): - """Pretty print the object and display it through a pager. - - %page [options] OBJECT - - If no object is given, use _ (last output). - - Options: - - -r: page str(object), don't pretty-print it.""" - - # After a function contributed by Olivier Aubert, slightly modified. - - # Process options/args - opts, args = self.parse_options(parameter_s, 'r') - raw = 'r' in opts - - oname = args and args or '_' - info = self.shell._ofind(oname) - if info['found']: - txt = (raw and str or pformat)( info['obj'] ) - page.page(txt) - else: - print('Object `%s` not found' % oname) - - @line_magic - def pprint(self, parameter_s=''): - """Toggle pretty printing on/off.""" - ptformatter = self.shell.display_formatter.formatters['text/plain'] - ptformatter.pprint = bool(1 - ptformatter.pprint) - print('Pretty printing has been turned', - ['OFF','ON'][ptformatter.pprint]) - - @line_magic - def colors(self, parameter_s=''): - """Switch color scheme for prompts, info system and exception handlers. - - Currently implemented schemes: NoColor, Linux, LightBG. - - Color scheme names are not case-sensitive. - - Examples - -------- - To get a plain black and white terminal:: - - %colors nocolor - """ - def color_switch_err(name): - warn('Error changing %s color schemes.\n%s' % - (name, sys.exc_info()[1]), stacklevel=2) - - - new_scheme = parameter_s.strip() - if not new_scheme: - raise UsageError( - "%colors: you must specify a color scheme. See '%colors?'") - # local shortcut - shell = self.shell - - # Set shell colour scheme - try: - shell.colors = new_scheme - shell.refresh_style() - except: - color_switch_err('shell') - - # Set exception colors - try: - shell.InteractiveTB.set_colors(scheme = new_scheme) - shell.SyntaxTB.set_colors(scheme = new_scheme) - except: - color_switch_err('exception') - - # Set info (for 'object?') colors - if shell.color_info: - try: - shell.inspector.set_active_scheme(new_scheme) - except: - color_switch_err('object inspector') - else: - shell.inspector.set_active_scheme('NoColor') - - @line_magic - def xmode(self, parameter_s=''): - """Switch modes for the exception handlers. - - Valid modes: Plain, Context, Verbose, and Minimal. - - If called without arguments, acts as a toggle. - - When in verbose mode the value --show (and --hide) - will respectively show (or hide) frames with ``__tracebackhide__ = - True`` value set. - """ - - def xmode_switch_err(name): - warn('Error changing %s exception modes.\n%s' % - (name,sys.exc_info()[1])) - - shell = self.shell - if parameter_s.strip() == "--show": - shell.InteractiveTB.skip_hidden = False - return - if parameter_s.strip() == "--hide": - shell.InteractiveTB.skip_hidden = True - return - - new_mode = parameter_s.strip().capitalize() - try: - shell.InteractiveTB.set_mode(mode=new_mode) - print('Exception reporting mode:',shell.InteractiveTB.mode) - except: - xmode_switch_err('user') - - @line_magic - def quickref(self, arg): - """ Show a quick reference sheet """ - from IPython.core.usage import quick_reference - qr = quick_reference + self._magic_docs(brief=True) - page.page(qr) - - @line_magic - def doctest_mode(self, parameter_s=''): - """Toggle doctest mode on and off. - - This mode is intended to make IPython behave as much as possible like a - plain Python shell, from the perspective of how its prompts, exceptions - and output look. This makes it easy to copy and paste parts of a - session into doctests. It does so by: - - - Changing the prompts to the classic ``>>>`` ones. - - Changing the exception reporting mode to 'Plain'. - - Disabling pretty-printing of output. - - Note that IPython also supports the pasting of code snippets that have - leading '>>>' and '...' prompts in them. This means that you can paste - doctests from files or docstrings (even if they have leading - whitespace), and the code will execute correctly. You can then use - '%history -t' to see the translated history; this will give you the - input after removal of all the leading prompts and whitespace, which - can be pasted back into an editor. - - With these features, you can switch into this mode easily whenever you - need to do testing and changes to doctests, without having to leave - your existing IPython session. - """ - - # Shorthands - shell = self.shell - meta = shell.meta - disp_formatter = self.shell.display_formatter - ptformatter = disp_formatter.formatters['text/plain'] - # dstore is a data store kept in the instance metadata bag to track any - # changes we make, so we can undo them later. - dstore = meta.setdefault('doctest_mode',Struct()) - save_dstore = dstore.setdefault - - # save a few values we'll need to recover later - mode = save_dstore('mode',False) - save_dstore('rc_pprint',ptformatter.pprint) - save_dstore('xmode',shell.InteractiveTB.mode) - save_dstore('rc_separate_out',shell.separate_out) - save_dstore('rc_separate_out2',shell.separate_out2) - save_dstore('rc_separate_in',shell.separate_in) - save_dstore('rc_active_types',disp_formatter.active_types) - - if not mode: - # turn on - - # Prompt separators like plain python - shell.separate_in = '' - shell.separate_out = '' - shell.separate_out2 = '' - - - ptformatter.pprint = False - disp_formatter.active_types = ['text/plain'] - - shell.magic('xmode Plain') - else: - # turn off - shell.separate_in = dstore.rc_separate_in - - shell.separate_out = dstore.rc_separate_out - shell.separate_out2 = dstore.rc_separate_out2 - - ptformatter.pprint = dstore.rc_pprint - disp_formatter.active_types = dstore.rc_active_types - - 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) - - # Store new mode and inform - dstore.mode = bool(not mode) - mode_label = ['OFF','ON'][dstore.mode] - print('Doctest mode is:', mode_label) - - @line_magic - def gui(self, parameter_s=''): - """Enable or disable IPython GUI event loop integration. - - %gui [GUINAME] - - This magic replaces IPython's threaded shells that were activated - using the (pylab/wthread/etc.) command line flags. GUI toolkits - can now be enabled at runtime and keyboard - interrupts should work without any problems. The following toolkits - are supported: wxPython, PyQt4, PyGTK, Tk and Cocoa (OSX):: - - %gui wx # enable wxPython event loop integration - %gui qt4|qt # enable PyQt4 event loop integration - %gui qt5 # enable PyQt5 event loop integration - %gui gtk # enable PyGTK event loop integration - %gui gtk3 # enable Gtk3 event loop integration - %gui gtk4 # enable Gtk4 event loop integration - %gui tk # enable Tk event loop integration - %gui osx # enable Cocoa event loop integration - # (requires %matplotlib 1.1) - %gui # disable all event loop integration - - WARNING: after any of these has been called you can simply create - an application object, but DO NOT start the event loop yourself, as - we have already handled that. - """ - opts, arg = self.parse_options(parameter_s, '') - if arg=='': arg = None - try: - return self.shell.enable_gui(arg) - except Exception as e: - # print simple error message, rather than traceback if we can't - # hook up the GUI - error(str(e)) - - @skip_doctest - @line_magic - def precision(self, s=''): - """Set floating point precision for pretty printing. - - Can set either integer precision or a format string. - - If numpy has been imported and precision is an int, - numpy display precision will also be set, via ``numpy.set_printoptions``. - - If no argument is given, defaults will be restored. - - Examples - -------- - :: - - In [1]: from math import pi - - In [2]: %precision 3 - Out[2]: u'%.3f' - - In [3]: pi - Out[3]: 3.142 - - In [4]: %precision %i - Out[4]: u'%i' - - In [5]: pi - Out[5]: 3 - - In [6]: %precision %e - Out[6]: u'%e' - - In [7]: pi**10 - Out[7]: 9.364805e+04 - - In [8]: %precision - Out[8]: u'%r' - - In [9]: pi**10 - Out[9]: 93648.047476082982 - """ - ptformatter = self.shell.display_formatter.formatters['text/plain'] - ptformatter.float_precision = s - return ptformatter.float_format - - @magic_arguments.magic_arguments() - @magic_arguments.argument( - 'filename', type=str, - help='Notebook name or filename' - ) - @line_magic - def notebook(self, s): - """Export and convert IPython notebooks. - - This function can export the current IPython history to a notebook file. - For example, to export the history to "foo.ipynb" do "%notebook foo.ipynb". - """ - args = magic_arguments.parse_argstring(self.notebook, s) - outfname = os.path.expanduser(args.filename) - - from nbformat import write, v4 - - cells = [] - hist = list(self.shell.history_manager.get_range()) - if(len(hist)<=1): - raise ValueError('History is empty, cannot export') - for session, execution_count, source in hist[:-1]: - cells.append(v4.new_code_cell( - execution_count=execution_count, - source=source - )) - nb = v4.new_notebook(cells=cells) - with io.open(outfname, "w", encoding="utf-8") as f: - write(nb, f, version=4) - -@magics_class -class AsyncMagics(BasicMagics): - - @line_magic - def autoawait(self, parameter_s): - """ - Allow to change the status of the autoawait option. - - This allow you to set a specific asynchronous code runner. - - If no value is passed, print the currently used asynchronous integration - and whether it is activated. - - It can take a number of value evaluated in the following order: - - - False/false/off deactivate autoawait integration - - True/true/on activate autoawait integration using configured default - loop - - asyncio/curio/trio activate autoawait integration and use integration - with said library. - - - `sync` turn on the pseudo-sync integration (mostly used for - `IPython.embed()` which does not run IPython with a real eventloop and - deactivate running asynchronous code. Turning on Asynchronous code with - the pseudo sync loop is undefined behavior and may lead IPython to crash. - - If the passed parameter does not match any of the above and is a python - identifier, get said object from user namespace and set it as the - runner, and activate autoawait. - - If the object is a fully qualified object name, attempt to import it and - set it as the runner, and activate autoawait. - - The exact behavior of autoawait is experimental and subject to change - across version of IPython and Python. - """ - - param = parameter_s.strip() - d = {True: "on", False: "off"} - - if not param: - print("IPython autoawait is `{}`, and set to use `{}`".format( - d[self.shell.autoawait], - self.shell.loop_runner - )) - return None - - if param.lower() in ('false', 'off'): - self.shell.autoawait = False - return None - if param.lower() in ('true', 'on'): - self.shell.autoawait = True - return None - - if param in self.shell.loop_runner_map: - self.shell.loop_runner, self.shell.autoawait = self.shell.loop_runner_map[param] - return None - - if param in self.shell.user_ns : - self.shell.loop_runner = self.shell.user_ns[param] - self.shell.autoawait = True - return None - - runner = import_item(param) - - self.shell.loop_runner = runner - self.shell.autoawait = True diff --git a/contrib/python/ipython/py3/IPython/core/magics/code.py b/contrib/python/ipython/py3/IPython/core/magics/code.py deleted file mode 100644 index 65ba52b8bb..0000000000 --- a/contrib/python/ipython/py3/IPython/core/magics/code.py +++ /dev/null @@ -1,755 +0,0 @@ -"""Implementation of code management magic functions. -""" -#----------------------------------------------------------------------------- -# Copyright (c) 2012 The IPython Development Team. -# -# Distributed under the terms of the Modified BSD License. -# -# The full license is in the file COPYING.txt, distributed with this software. -#----------------------------------------------------------------------------- - -#----------------------------------------------------------------------------- -# Imports -#----------------------------------------------------------------------------- - -# Stdlib -import inspect -import io -import os -import re -import sys -import ast -from itertools import chain -from urllib.request import Request, urlopen -from urllib.parse import urlencode -from pathlib import Path - -# Our own packages -from IPython.core.error import TryNext, StdinNotImplementedError, UsageError -from IPython.core.macro import Macro -from IPython.core.magic import Magics, magics_class, line_magic -from IPython.core.oinspect import find_file, find_source_lines -from IPython.core.release import version -from IPython.testing.skipdoctest import skip_doctest -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.text import get_text_list - -#----------------------------------------------------------------------------- -# Magic implementation classes -#----------------------------------------------------------------------------- - -# Used for exception handling in magic_edit -class MacroToEdit(ValueError): pass - -ipython_input_pat = re.compile(r"<ipython\-input\-(\d+)-[a-z\d]+>$") - -# To match, e.g. 8-10 1:5 :10 3- -range_re = re.compile(r""" -(?P<start>\d+)? -((?P<sep>[\-:]) - (?P<end>\d+)?)? -$""", re.VERBOSE) - - -def extract_code_ranges(ranges_str): - """Turn a string of range for %%load into 2-tuples of (start, stop) - ready to use as a slice of the content split by lines. - - Examples - -------- - list(extract_input_ranges("5-10 2")) - [(4, 10), (1, 2)] - """ - for range_str in ranges_str.split(): - rmatch = range_re.match(range_str) - if not rmatch: - continue - sep = rmatch.group("sep") - start = rmatch.group("start") - end = rmatch.group("end") - - if sep == '-': - start = int(start) - 1 if start else None - end = int(end) if end else None - elif sep == ':': - start = int(start) - 1 if start else None - end = int(end) - 1 if end else None - else: - end = int(start) - start = int(start) - 1 - yield (start, end) - - -def extract_symbols(code, symbols): - """ - Return a tuple (blocks, not_found) - where ``blocks`` is a list of code fragments - for each symbol parsed from code, and ``not_found`` are - symbols not found in the code. - - For example:: - - In [1]: code = '''a = 10 - ...: def b(): return 42 - ...: class A: pass''' - - In [2]: extract_symbols(code, 'A,b,z') - Out[2]: (['class A: pass\\n', 'def b(): return 42\\n'], ['z']) - """ - symbols = symbols.split(',') - - # this will raise SyntaxError if code isn't valid Python - py_code = ast.parse(code) - - marks = [(getattr(s, 'name', None), s.lineno) for s in py_code.body] - code = code.split('\n') - - symbols_lines = {} - - # we already know the start_lineno of each symbol (marks). - # To find each end_lineno, we traverse in reverse order until each - # non-blank line - end = len(code) - for name, start in reversed(marks): - while not code[end - 1].strip(): - end -= 1 - if name: - symbols_lines[name] = (start - 1, end) - end = start - 1 - - # Now symbols_lines is a map - # {'symbol_name': (start_lineno, end_lineno), ...} - - # fill a list with chunks of codes for each requested symbol - blocks = [] - not_found = [] - for symbol in symbols: - if symbol in symbols_lines: - start, end = symbols_lines[symbol] - blocks.append('\n'.join(code[start:end]) + '\n') - else: - not_found.append(symbol) - - 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 - - -class InteractivelyDefined(Exception): - """Exception for interactively defined variable in magic_edit""" - def __init__(self, index): - self.index = index - - -@magics_class -class CodeMagics(Magics): - """Magics related to code management (loading, saving, editing, ...).""" - - def __init__(self, *args, **kwargs): - self._knowntemps = set() - super(CodeMagics, self).__init__(*args, **kwargs) - - @line_magic - def save(self, parameter_s=''): - """Save a set of lines or a macro to a given filename. - - Usage:\\ - %save [options] filename [history] - - Options: - - -r: use 'raw' input. By default, the 'processed' history is used, - so that magics are loaded in their transformed version to valid - Python. If this option is given, the raw input as typed as the - command line is used instead. - - -f: force overwrite. If file exists, %save will prompt for overwrite - unless -f is given. - - -a: append to the file instead of overwriting it. - - The history argument uses the same syntax as %history for input ranges, - then saves the lines to the filename you specify. - - If no ranges are specified, saves history of the current session up to - this point. - - It adds a '.py' extension to the file if you don't do so yourself, and - it asks for confirmation before overwriting existing files. - - If `-r` option is used, the default extension is `.ipy`. - """ - - opts,args = self.parse_options(parameter_s,'fra',mode='list') - if not args: - raise UsageError('Missing filename.') - raw = 'r' in opts - force = 'f' in opts - append = 'a' in opts - mode = 'a' if append else 'w' - ext = '.ipy' if raw else '.py' - fname, codefrom = args[0], " ".join(args[1:]) - if not fname.endswith(('.py','.ipy')): - fname += ext - fname = os.path.expanduser(fname) - file_exists = os.path.isfile(fname) - if file_exists and not force and not append: - try: - overwrite = self.shell.ask_yes_no('File `%s` exists. Overwrite (y/[N])? ' % fname, default='n') - except StdinNotImplementedError: - print("File `%s` exists. Use `%%save -f %s` to force overwrite" % (fname, parameter_s)) - return - if not overwrite : - print('Operation cancelled.') - return - try: - cmds = self.shell.find_user_code(codefrom,raw) - except (TypeError, ValueError) as e: - print(e.args[0]) - return - with io.open(fname, mode, encoding="utf-8") as f: - if not file_exists or not append: - f.write("# coding: utf-8\n") - f.write(cmds) - # make sure we end on a newline - if not cmds.endswith('\n'): - f.write('\n') - print('The following commands were written to file `%s`:' % fname) - print(cmds) - - @line_magic - def pastebin(self, parameter_s=''): - """Upload code to dpaste.com, returning the URL. - - Usage:\\ - %pastebin [-d "Custom description"][-e 24] 1-7 - - The argument can be an input history range, a filename, or the name of a - string or macro. - - If no arguments are given, uploads the history of this session up to - this point. - - Options: - - -d: Pass a custom description. The default will say - "Pasted from IPython". - -e: Pass number of days for the link to be expired. - The default will be 7 days. - """ - opts, args = self.parse_options(parameter_s, "d:e:") - - try: - code = self.shell.find_user_code(args) - except (ValueError, TypeError) as e: - print(e.args[0]) - return - - expiry_days = 7 - try: - expiry_days = int(opts.get("e", 7)) - except ValueError as e: - print(e.args[0].capitalize()) - return - if expiry_days < 1 or expiry_days > 365: - print("Expiry days should be in range of 1 to 365") - return - - post_data = urlencode( - { - "title": opts.get("d", "Pasted from IPython"), - "syntax": "python", - "content": code, - "expiry_days": expiry_days, - } - ).encode("utf-8") - - request = Request( - "https://dpaste.com/api/v2/", - headers={"User-Agent": "IPython v{}".format(version)}, - ) - response = urlopen(request, post_data) - return response.headers.get('Location') - - @line_magic - def loadpy(self, arg_s): - """Alias of `%load` - - `%loadpy` has gained some flexibility and dropped the requirement of a `.py` - extension. So it has been renamed simply into %load. You can look at - `%load`'s docstring for more info. - """ - self.load(arg_s) - - @line_magic - def load(self, arg_s): - """Load code into the current frontend. - - Usage:\\ - %load [options] source - - where source can be a filename, URL, input history range, macro, or - element in the user namespace - - If no arguments are given, loads the history of this session up to this - point. - - Options: - - -r <lines>: Specify lines or ranges of lines to load from the source. - Ranges could be specified as x-y (x..y) or in python-style x:y - (x..(y-1)). Both limits x and y can be left blank (meaning the - beginning and end of the file, respectively). - - -s <symbols>: Specify function or classes to load from python source. - - -y : Don't ask confirmation for loading source above 200 000 characters. - - -n : Include the user's namespace when searching for source code. - - This magic command can either take a local filename, a URL, an history - range (see %history) or a macro as argument, it will prompt for - confirmation before loading source with more than 200 000 characters, unless - -y flag is passed or if the frontend does not support raw_input:: - - %load - %load myscript.py - %load 7-27 - %load myMacro - %load http://www.example.com/myscript.py - %load -r 5-10 myscript.py - %load -r 10-20,30,40: foo.py - %load -s MyClass,wonder_function myscript.py - %load -n MyClass - %load -n my_module.wonder_function - """ - opts,args = self.parse_options(arg_s,'yns:r:') - search_ns = 'n' in opts - contents = self.shell.find_user_code(args, search_ns=search_ns) - - if 's' in opts: - try: - blocks, not_found = extract_symbols(contents, opts['s']) - except SyntaxError: - # non python code - error("Unable to parse the input as valid Python code") - return - - if len(not_found) == 1: - warn('The symbol `%s` was not found' % not_found[0]) - elif len(not_found) > 1: - warn('The symbols %s were not found' % get_text_list(not_found, - wrap_item_with='`') - ) - - contents = '\n'.join(blocks) - - if 'r' in opts: - ranges = opts['r'].replace(',', ' ') - 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))) - - l = len(contents) - - # 200 000 is ~ 2500 full 80 character lines - # so in average, more than 5000 lines - if l > 200000 and 'y' not in opts: - try: - ans = self.shell.ask_yes_no(("The text you're trying to load seems pretty big"\ - " (%d characters). Continue (y/[N]) ?" % l), default='n' ) - except StdinNotImplementedError: - #assume yes if raw input not implemented - ans = True - - if ans is False : - print('Operation cancelled.') - return - - contents = "# %load {}\n".format(arg_s) + contents - - self.shell.set_next_input(contents, replace=True) - - @staticmethod - def _find_edit_target(shell, args, opts, last_call): - """Utility method used by magic_edit to find what to edit.""" - - def make_filename(arg): - "Make a filename from the given args" - try: - filename = get_py_filename(arg) - except IOError: - # If it ends with .py but doesn't already exist, assume we want - # a new file. - if arg.endswith('.py'): - filename = arg - else: - filename = None - return filename - - # Set a few locals from the options for convenience: - opts_prev = 'p' in opts - opts_raw = 'r' in opts - - # custom exceptions - class DataIsObject(Exception): pass - - # Default line number value - lineno = opts.get('n',None) - - if opts_prev: - args = '_%s' % last_call[0] - if args not in shell.user_ns: - args = last_call[1] - - # by default this is done with temp files, except when the given - # arg is a filename - use_temp = True - - data = '' - - # First, see if the arguments should be a filename. - filename = make_filename(args) - if filename: - use_temp = False - elif args: - # Mode where user specifies ranges of lines, like in %macro. - data = shell.extract_input_lines(args, opts_raw) - if not data: - try: - # Load the parameter given as a variable. If not a string, - # process it as an object instead (below) - - #print '*** args',args,'type',type(args) # dbg - data = eval(args, shell.user_ns) - if not isinstance(data, str): - raise DataIsObject - - except (NameError,SyntaxError): - # given argument is not a variable, try as a filename - filename = make_filename(args) - if filename is None: - warn("Argument given (%s) can't be found as a variable " - "or as a filename." % args) - return (None, None, None) - use_temp = False - - except DataIsObject as e: - # macros have a special edit function - if isinstance(data, Macro): - raise MacroToEdit(data) from e - - # For objects, try to edit the file where they are defined - filename = find_file(data) - if filename: - if 'fakemodule' in filename.lower() and \ - inspect.isclass(data): - # class created by %edit? Try to find source - # by looking for method definitions instead, the - # __module__ in those classes is FakeModule. - attrs = [getattr(data, aname) for aname in dir(data)] - for attr in attrs: - if not inspect.ismethod(attr): - continue - filename = find_file(attr) - if filename and \ - 'fakemodule' not in filename.lower(): - # change the attribute to be the edit - # target instead - data = attr - break - - m = ipython_input_pat.match(os.path.basename(filename)) - if m: - raise InteractivelyDefined(int(m.groups()[0])) from e - - datafile = 1 - if filename is None: - filename = make_filename(args) - datafile = 1 - if filename is not None: - # only warn about this if we get a real name - warn('Could not find file where `%s` is defined.\n' - 'Opening a file named `%s`' % (args, filename)) - # Now, make sure we can actually read the source (if it was - # in a temp file it's gone by now). - if datafile: - if lineno is None: - lineno = find_source_lines(data) - if lineno is None: - filename = make_filename(args) - if filename is None: - warn('The file where `%s` was defined ' - 'cannot be read or found.' % data) - return (None, None, None) - use_temp = False - - if use_temp: - filename = shell.mktempfile(data) - print('IPython will make a temporary file named:',filename) - - # use last_call to remember the state of the previous call, but don't - # let it be clobbered by successive '-p' calls. - try: - last_call[0] = shell.displayhook.prompt_count - if not opts_prev: - last_call[1] = args - except: - pass - - - return filename, lineno, use_temp - - def _edit_macro(self,mname,macro): - """open an editor with the macro data in a file""" - filename = self.shell.mktempfile(macro.value) - self.shell.hooks.editor(filename) - - # and make a new macro object, to replace the old one - mvalue = Path(filename).read_text(encoding="utf-8") - self.shell.user_ns[mname] = Macro(mvalue) - - @skip_doctest - @line_magic - def edit(self, parameter_s='',last_call=['','']): - """Bring up an editor and execute the resulting code. - - Usage: - %edit [options] [args] - - %edit runs IPython's editor hook. The default version of this hook is - set to call the editor specified by your $EDITOR environment variable. - If this isn't found, it will default to vi under Linux/Unix and to - notepad under Windows. See the end of this docstring for how to change - the editor hook. - - You can also set the value of this editor via the - ``TerminalInteractiveShell.editor`` option in your configuration file. - This is useful if you wish to use a different editor from your typical - default with IPython (and for Windows users who typically don't set - environment variables). - - This command allows you to conveniently edit multi-line code right in - your IPython session. - - If called without arguments, %edit opens up an empty editor with a - temporary file and will execute the contents of this file when you - close it (don't forget to save it!). - - - Options: - - -n <number>: open the editor at a specified line number. By default, - the IPython editor hook uses the unix syntax 'editor +N filename', but - you can configure this by providing your own modified hook if your - favorite editor supports line-number specifications with a different - syntax. - - -p: this will call the editor with the same data as the previous time - it was used, regardless of how long ago (in your current session) it - was. - - -r: use 'raw' input. This option only applies to input taken from the - user's history. By default, the 'processed' history is used, so that - magics are loaded in their transformed version to valid Python. If - this option is given, the raw input as typed as the command line is - used instead. When you exit the editor, it will be executed by - IPython's own processor. - - -x: do not execute the edited code immediately upon exit. This is - mainly useful if you are editing programs which need to be called with - command line arguments, which you can then do using %run. - - - Arguments: - - If arguments are given, the following possibilities exist: - - - If the argument is a filename, IPython will load that into the - editor. It will execute its contents with execfile() when you exit, - loading any code in the file into your interactive namespace. - - - The arguments are ranges of input history, e.g. "7 ~1/4-6". - The syntax is the same as in the %history magic. - - - If the argument is a string variable, its contents are loaded - into the editor. You can thus edit any string which contains - python code (including the result of previous edits). - - - If the argument is the name of an object (other than a string), - IPython will try to locate the file where it was defined and open the - editor at the point where it is defined. You can use `%edit function` - to load an editor exactly at the point where 'function' is defined, - edit it and have the file be executed automatically. - - - If the object is a macro (see %macro for details), this opens up your - specified editor with a temporary file containing the macro's data. - Upon exit, the macro is reloaded with the contents of the file. - - Note: opening at an exact line is only supported under Unix, and some - editors (like kedit and gedit up to Gnome 2.8) do not understand the - '+NUMBER' parameter necessary for this feature. Good editors like - (X)Emacs, vi, jed, pico and joe all do. - - After executing your code, %edit will return as output the code you - typed in the editor (except when it was an existing file). This way - you can reload the code in further invocations of %edit as a variable, - via _<NUMBER> or Out[<NUMBER>], where <NUMBER> is the prompt number of - the output. - - Note that %edit is also available through the alias %ed. - - This is an example of creating a simple function inside the editor and - then modifying it. First, start up the editor:: - - In [1]: edit - Editing... done. Executing edited code... - Out[1]: 'def foo():\\n print "foo() was defined in an editing - session"\\n' - - We can then call the function foo():: - - In [2]: foo() - foo() was defined in an editing session - - Now we edit foo. IPython automatically loads the editor with the - (temporary) file where foo() was previously defined:: - - In [3]: edit foo - Editing... done. Executing edited code... - - And if we call foo() again we get the modified version:: - - In [4]: foo() - foo() has now been changed! - - Here is an example of how to edit a code snippet successive - times. First we call the editor:: - - In [5]: edit - Editing... done. Executing edited code... - hello - Out[5]: "print 'hello'\\n" - - Now we call it again with the previous output (stored in _):: - - In [6]: edit _ - Editing... done. Executing edited code... - hello world - Out[6]: "print 'hello world'\\n" - - Now we call it with the output #8 (stored in _8, also as Out[8]):: - - In [7]: edit _8 - Editing... done. Executing edited code... - hello again - Out[7]: "print 'hello again'\\n" - - - Changing the default editor hook: - - If you wish to write your own editor hook, you can put it in a - configuration file which you load at startup time. The default hook - is defined in the IPython.core.hooks module, and you can use that as a - starting example for further modifications. That file also has - general instructions on how to set a new hook for use once you've - defined it.""" - opts,args = self.parse_options(parameter_s,'prxn:') - - try: - filename, lineno, is_temp = self._find_edit_target(self.shell, - args, opts, last_call) - except MacroToEdit as e: - self._edit_macro(args, e.args[0]) - return - except InteractivelyDefined as e: - print("Editing In[%i]" % e.index) - args = str(e.index) - filename, lineno, is_temp = self._find_edit_target(self.shell, - args, opts, last_call) - if filename is None: - # nothing was found, warnings have already been issued, - # just give up. - return - - if is_temp: - self._knowntemps.add(filename) - elif (filename in self._knowntemps): - is_temp = True - - - # do actual editing here - print('Editing...', end=' ') - sys.stdout.flush() - filepath = Path(filename) - try: - # Quote filenames that may have spaces in them when opening - # the editor - quoted = filename = str(filepath.absolute()) - if " " in quoted: - quoted = "'%s'" % quoted - self.shell.hooks.editor(quoted, lineno) - except TryNext: - warn('Could not open editor') - return - - # XXX TODO: should this be generalized for all string vars? - # For now, this is special-cased to blocks created by cpaste - if args.strip() == "pasted_block": - self.shell.user_ns["pasted_block"] = filepath.read_text(encoding="utf-8") - - if 'x' in opts: # -x prevents actual execution - print() - else: - print('done. Executing edited code...') - with preserve_keys(self.shell.user_ns, '__file__'): - if not is_temp: - self.shell.user_ns["__file__"] = filename - if "r" in opts: # Untranslated IPython code - source = filepath.read_text(encoding="utf-8") - self.shell.run_cell(source, store_history=False) - else: - self.shell.safe_execfile(filename, self.shell.user_ns, - self.shell.user_ns) - - if is_temp: - try: - return filepath.read_text(encoding="utf-8") - except IOError as msg: - if Path(msg.filename) == filepath: - warn('File not found. Did you forget to save?') - return - else: - self.shell.showtraceback() diff --git a/contrib/python/ipython/py3/IPython/core/magics/config.py b/contrib/python/ipython/py3/IPython/core/magics/config.py deleted file mode 100644 index c1387b601b..0000000000 --- a/contrib/python/ipython/py3/IPython/core/magics/config.py +++ /dev/null @@ -1,187 +0,0 @@ -"""Implementation of configuration-related magic functions. -""" -#----------------------------------------------------------------------------- -# Copyright (c) 2012 The IPython Development Team. -# -# Distributed under the terms of the Modified BSD License. -# -# The full license is in the file COPYING.txt, distributed with this software. -#----------------------------------------------------------------------------- - -#----------------------------------------------------------------------------- -# Imports -#----------------------------------------------------------------------------- - -# Stdlib -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 - -#----------------------------------------------------------------------------- -# Magic implementation classes -#----------------------------------------------------------------------------- - -reg = re.compile(r'^\w+\.\w+$') -@magics_class -class ConfigMagics(Magics): - - def __init__(self, shell): - super(ConfigMagics, self).__init__(shell) - self.configurables = [] - - @line_magic - def config(self, s): - """configure IPython - - %config Class[.trait=value] - - This magic exposes most of the IPython config system. Any - Configurable class should be able to be configured with the simple - line:: - - %config Class.trait=value - - Where `value` will be resolved in the user's namespace, if it is an - expression or variable name. - - Examples - -------- - - To see what classes are available for config, pass no arguments:: - - In [1]: %config - Available objects for config: - AliasManager - DisplayFormatter - HistoryManager - IPCompleter - LoggingMagics - MagicsManager - OSMagics - PrefilterManager - ScriptMagics - TerminalInteractiveShell - - To view what is configurable on a given class, just pass the class - name:: - - In [2]: %config IPCompleter - IPCompleter(Completer) options - ---------------------------- - IPCompleter.backslash_combining_completions=<Bool> - Enable unicode completions, e.g. \\alpha<tab> . Includes completion of latex - commands, unicode names, and expanding unicode characters back to latex - commands. - Current: True - IPCompleter.debug=<Bool> - Enable debug for the Completer. Mostly print extra information for - experimental jedi integration. - Current: False - IPCompleter.greedy=<Bool> - Activate greedy completion - PENDING DEPRECATION. 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. - Current: False - IPCompleter.jedi_compute_type_timeout=<Int> - Experimental: restrict time (in milliseconds) during which Jedi can compute types. - Set to 0 to stop computing types. Non-zero value lower than 100ms may hurt - performance by preventing jedi to build its cache. - Current: 400 - IPCompleter.limit_to__all__=<Bool> - 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 - Current: False - IPCompleter.merge_completions=<Bool> - Whether to merge completion results into a single list - If False, only the completion results from the first non-empty - completer will be returned. - Current: True - IPCompleter.omit__names=<Enum> - Instruct the completer to omit private method names - Specifically, when completing on ``object.<tab>``. - When 2 [default]: all names that start with '_' will be excluded. - When 1: all 'magic' names (``__foo__``) will be excluded. - When 0: nothing will be excluded. - Choices: any of [0, 1, 2] - Current: 2 - IPCompleter.profile_completions=<Bool> - If True, emit profiling data for completion subsystem using cProfile. - Current: False - IPCompleter.profiler_output_dir=<Unicode> - Template for path at which to output profile data for completions. - Current: '.completion_profiles' - IPCompleter.use_jedi=<Bool> - Experimental: Use Jedi to generate autocompletions. Default to True if jedi - is installed. - Current: True - - but the real use is in setting values:: - - In [3]: %config IPCompleter.greedy = True - - and these values are read from the user_ns if they are variables:: - - In [4]: feeling_greedy=False - - In [5]: %config IPCompleter.greedy = feeling_greedy - - """ - from traitlets.config.loader import Config - # some IPython objects are Configurable, but do not yet have - # any configurable traits. Exclude them from the effects of - # this magic, as their presence is just noise: - configurables = sorted(set([ c for c in self.shell.configurables - if c.__class__.class_traits(config=True) - ]), key=lambda x: x.__class__.__name__) - classnames = [ c.__class__.__name__ for c in configurables ] - - line = s.strip() - if not line: - # print available configurable names - print("Available objects for config:") - for name in classnames: - print(" ", name) - return - elif line in classnames: - # `%config TerminalInteractiveShell` will print trait info for - # TerminalInteractiveShell - c = configurables[classnames.index(line)] - cls = c.__class__ - help = cls.class_get_help(c) - # strip leading '--' from cl-args: - help = re.sub(re.compile(r'^--', re.MULTILINE), '', help) - print(help) - return - elif reg.match(line): - cls, attr = line.split('.') - return getattr(configurables[classnames.index(cls)],attr) - elif '=' not in line: - msg = "Invalid config statement: %r, "\ - "should be `Class.trait = value`." - - ll = line.lower() - for classname in classnames: - if ll == classname.lower(): - msg = msg + '\nDid you mean %s (note the case)?' % classname - break - - raise UsageError( msg % line) - - # otherwise, assume we are setting configurables. - # leave quotes on args when splitting, because we want - # unquoted args to eval in user_ns - cfg = Config() - exec("cfg."+line, self.shell.user_ns, locals()) - - for configurable in configurables: - try: - configurable.update_config(cfg) - except Exception as e: - error(e) diff --git a/contrib/python/ipython/py3/IPython/core/magics/display.py b/contrib/python/ipython/py3/IPython/core/magics/display.py deleted file mode 100644 index 6c0eff6884..0000000000 --- a/contrib/python/ipython/py3/IPython/core/magics/display.py +++ /dev/null @@ -1,93 +0,0 @@ -"""Simple magics for display formats""" -#----------------------------------------------------------------------------- -# Copyright (c) 2012 The IPython Development Team. -# -# Distributed under the terms of the Modified BSD License. -# -# The full license is in the file COPYING.txt, distributed with this software. -#----------------------------------------------------------------------------- - -#----------------------------------------------------------------------------- -# Imports -#----------------------------------------------------------------------------- - -# Our own packages -from IPython.display import display, Javascript, Latex, SVG, HTML, Markdown -from IPython.core.magic import ( - Magics, magics_class, cell_magic -) -from IPython.core import magic_arguments - -#----------------------------------------------------------------------------- -# Magic implementation classes -#----------------------------------------------------------------------------- - - -@magics_class -class DisplayMagics(Magics): - """Magics for displaying various output types with literals - - 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` - - Starting with IPython 8.0 %%javascript is pending deprecation to be replaced - by a more flexible system - - Please See https://github.com/ipython/ipython/issues/13376 - """ - self.javascript(line, cell) - - @cell_magic - def javascript(self, line, cell): - """Run the cell block of Javascript code - - Starting with IPython 8.0 %%javascript is pending deprecation to be replaced - by a more flexible system - - Please See https://github.com/ipython/ipython/issues/13376 - """ - display(Javascript(cell)) - - - @cell_magic - def latex(self, line, cell): - """Render the cell as a block of LaTeX - - The subset of LaTeX which is supported depends on the implementation in - 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)) - - @cell_magic - def svg(self, line, cell): - """Render the cell as an SVG literal""" - display(SVG(cell)) - - @magic_arguments.magic_arguments() - @magic_arguments.argument( - '--isolated', action='store_true', default=False, - help="""Annotate the cell as 'isolated'. -Isolated cells are rendered inside their own <iframe> tag""" - ) - @cell_magic - def html(self, line, cell): - """Render the cell as a block of HTML""" - args = magic_arguments.parse_argstring(self.html, line) - html = HTML(cell) - if args.isolated: - display(html, metadata={'text/html':{'isolated':True}}) - else: - display(html) - - @cell_magic - def markdown(self, line, cell): - """Render the cell as Markdown text block""" - display(Markdown(cell)) diff --git a/contrib/python/ipython/py3/IPython/core/magics/execution.py b/contrib/python/ipython/py3/IPython/core/magics/execution.py deleted file mode 100644 index da7f780b9c..0000000000 --- a/contrib/python/ipython/py3/IPython/core/magics/execution.py +++ /dev/null @@ -1,1510 +0,0 @@ -# -*- coding: utf-8 -*- -"""Implementation of execution-related magic functions.""" - -# Copyright (c) IPython Development Team. -# Distributed under the terms of the Modified BSD License. - - -import ast -import bdb -import builtins as builtin_mod -import cProfile as profile -import gc -import itertools -import math -import os -import pstats -import re -import shlex -import sys -import time -import timeit -from ast import Module -from io import StringIO -from logging import error -from pathlib import Path -from pdb import Restart -from warnings import warn - -from IPython.core import magic_arguments, oinspect, page -from IPython.core.error import UsageError -from IPython.core.macro import Macro -from IPython.core.magic import ( - Magics, - cell_magic, - line_cell_magic, - line_magic, - magics_class, - needs_local_scope, - no_var_expand, - on_off, -) -from IPython.testing.skipdoctest import skip_doctest -from IPython.utils.capture import capture_output -from IPython.utils.contexts import preserve_keys -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.timing import clock, clock2 - -#----------------------------------------------------------------------------- -# Magic implementation classes -#----------------------------------------------------------------------------- - - -class TimeitResult(object): - """ - Object returned by the timeit magic with info about the run. - - 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) - compile_time: (float) time of statement compilation (s) - - """ - def __init__(self, loops, repeat, best, worst, all_runs, compile_time, precision): - self.loops = loops - self.repeat = repeat - self.best = best - self.worst = worst - self.all_runs = all_runs - self.compile_time = compile_time - self._precision = precision - self.timings = [ dt / self.loops for dt in all_runs] - - @property - def average(self): - return math.fsum(self.timings) / len(self.timings) - - @property - def stdev(self): - mean = self.average - return (math.fsum([(x - mean) ** 2 for x in self.timings]) / len(self.timings)) ** 0.5 - - def __str__(self): - pm = '+-' - if hasattr(sys.stdout, 'encoding') and sys.stdout.encoding: - try: - u'\xb1'.encode(sys.stdout.encoding) - pm = u'\xb1' - except: - pass - return "{mean} {pm} {std} per loop (mean {pm} std. dev. of {runs} run{run_plural}, {loops:,} loop{loop_plural} each)".format( - pm=pm, - runs=self.repeat, - loops=self.loops, - loop_plural="" if self.loops == 1 else "s", - run_plural="" if self.repeat == 1 else "s", - mean=_format_time(self.average, self._precision), - std=_format_time(self.stdev, self._precision), - ) - - def _repr_pretty_(self, p , cycle): - unic = self.__str__() - p.text(u'<TimeitResult : '+unic+u'>') - - -class TimeitTemplateFiller(ast.NodeTransformer): - """Fill in the AST template for timing execution. - - This is quite closely tied to the template definition, which is in - :meth:`ExecutionMagics.timeit`. - """ - def __init__(self, ast_setup, ast_stmt): - self.ast_setup = ast_setup - self.ast_stmt = ast_stmt - - def visit_FunctionDef(self, node): - "Fill in the setup statement" - self.generic_visit(node) - if node.name == "inner": - node.body[:1] = self.ast_setup.body - - return node - - def visit_For(self, node): - "Fill in the statement to be timed" - if getattr(getattr(node.body[0], 'value', None), 'id', None) == 'stmt': - node.body = self.ast_stmt.body - return node - - -class Timer(timeit.Timer): - """Timer class that explicitly uses self.inner - - which is an undocumented implementation detail of CPython, - not shared by PyPy. - """ - # Timer.timeit copied from CPython 3.4.2 - def timeit(self, number=timeit.default_number): - """Time 'number' executions of the main statement. - - To be precise, this executes the setup statement once, and - then returns the time it takes to execute the main statement - a number of times, as a float measured in seconds. The - argument is the number of times through the loop, defaulting - to one million. The main statement, the setup statement and - the timer function to be used are passed to the constructor. - """ - it = itertools.repeat(None, number) - gcold = gc.isenabled() - gc.disable() - try: - timing = self.inner(it, self.timer) - finally: - if gcold: - gc.enable() - return timing - - -@magics_class -class ExecutionMagics(Magics): - """Magics related to code execution, debugging, profiling, etc. - - """ - - def __init__(self, shell): - super(ExecutionMagics, self).__init__(shell) - # Default execution function used to actually run user code. - self.default_runner = None - - @skip_doctest - @no_var_expand - @line_cell_magic - def prun(self, parameter_s='', cell=None): - - """Run a statement through the python code profiler. - - Usage, in line mode: - %prun [options] statement - - Usage, in cell mode: - %%prun [options] [statement] - code... - code... - - In cell mode, the additional code lines are appended to the (possibly - empty) statement in the first line. Cell mode allows you to easily - profile multiline blocks without having to put them in a separate - function. - - The given statement (which doesn't require quote marks) is run via the - python profiler in a manner similar to the profile.run() function. - Namespaces are internally managed to work correctly; profile.run - cannot be used in IPython because it makes certain assumptions about - namespaces which do not hold under IPython. - - Options: - - -l <limit> - you can place restrictions on what or how much of the - profile gets printed. The limit value can be: - - * A string: only information for function names containing this string - is printed. - - * An integer: only these many lines are printed. - - * A float (between 0 and 1): this fraction of the report is printed - (for example, use a limit of 0.4 to see the topmost 40% only). - - You can combine several limits with repeated use of the option. For - example, ``-l __init__ -l 5`` will print only the topmost 5 lines of - information about class constructors. - - -r - return the pstats.Stats object generated by the profiling. This - object has all the information about the profile in it, and you can - later use it for further analysis or in other functions. - - -s <key> - sort profile by given key. You can provide more than one key - by using the option several times: '-s key1 -s key2 -s key3...'. The - default sorting key is 'time'. - - The following is copied verbatim from the profile documentation - referenced below: - - When more than one key is provided, additional keys are used as - secondary criteria when the there is equality in all keys selected - before them. - - Abbreviations can be used for any key names, as long as the - abbreviation is unambiguous. The following are the keys currently - defined: - - ============ ===================== - Valid Arg Meaning - ============ ===================== - "calls" call count - "cumulative" cumulative time - "file" file name - "module" file name - "pcalls" primitive call count - "line" line number - "name" function name - "nfl" name/file/line - "stdname" standard name - "time" internal time - ============ ===================== - - Note that all sorts on statistics are in descending order (placing - most time consuming items first), where as name, file, and line number - searches are in ascending order (i.e., alphabetical). The subtle - distinction between "nfl" and "stdname" is that the standard name is a - sort of the name as printed, which means that the embedded line - numbers get compared in an odd way. For example, lines 3, 20, and 40 - would (if the file names were the same) appear in the string order - "20" "3" and "40". In contrast, "nfl" does a numeric compare of the - line numbers. In fact, sort_stats("nfl") is the same as - sort_stats("name", "file", "line"). - - -T <filename> - save profile results as shown on screen to a text - file. The profile is still shown on screen. - - -D <filename> - save (via dump_stats) profile statistics to given - filename. This data is in a format understood by the pstats module, and - is generated by a call to the dump_stats() method of profile - objects. The profile is still shown on screen. - - -q - suppress output to the pager. Best used with -T and/or -D above. - - If you want to run complete programs under the profiler's control, use - ``%run -p [prof_opts] filename.py [args to program]`` where prof_opts - contains profiler specific options as described here. - - You can read the complete documentation for the profile module with:: - - In [1]: import profile; profile.help() - - .. versionchanged:: 7.3 - User variables are no longer expanded, - the magic line is always left unmodified. - - """ - opts, arg_str = self.parse_options(parameter_s, 'D:l:rs:T:q', - list_all=True, posix=False) - if cell is not None: - arg_str += '\n' + cell - arg_str = self.shell.transform_cell(arg_str) - return self._run_with_profiler(arg_str, opts, self.shell.user_ns) - - def _run_with_profiler(self, code, opts, namespace): - """ - Run `code` with profiler. Used by ``%prun`` and ``%run -p``. - - Parameters - ---------- - code : str - Code to be executed. - opts : Struct - Options parsed by `self.parse_options`. - namespace : dict - A dictionary for Python namespace (e.g., `self.shell.user_ns`). - - """ - - # Fill default values for unspecified options: - opts.merge(Struct(D=[''], l=[], s=['time'], T=[''])) - - prof = profile.Profile() - try: - prof = prof.runctx(code, namespace, namespace) - sys_exit = '' - except SystemExit: - sys_exit = """*** SystemExit exception caught in code being profiled.""" - - stats = pstats.Stats(prof).strip_dirs().sort_stats(*opts.s) - - lims = opts.l - if lims: - lims = [] # rebuild lims with ints/floats/strings - for lim in opts.l: - try: - lims.append(int(lim)) - except ValueError: - try: - lims.append(float(lim)) - except ValueError: - lims.append(lim) - - # Trap output. - stdout_trap = StringIO() - stats_stream = stats.stream - try: - stats.stream = stdout_trap - stats.print_stats(*lims) - finally: - stats.stream = stats_stream - - output = stdout_trap.getvalue() - output = output.rstrip() - - if 'q' not in opts: - page.page(output) - print(sys_exit, end=' ') - - dump_file = opts.D[0] - text_file = opts.T[0] - if dump_file: - prof.dump_stats(dump_file) - print( - f"\n*** Profile stats marshalled to file {repr(dump_file)}.{sys_exit}" - ) - if text_file: - pfile = Path(text_file) - pfile.touch(exist_ok=True) - pfile.write_text(output, encoding="utf-8") - - print( - f"\n*** Profile printout saved to text file {repr(text_file)}.{sys_exit}" - ) - - if 'r' in opts: - return stats - - return None - - @line_magic - def pdb(self, parameter_s=''): - """Control the automatic calling of the pdb interactive debugger. - - Call as '%pdb on', '%pdb 1', '%pdb off' or '%pdb 0'. If called without - argument it works as a toggle. - - When an exception is triggered, IPython can optionally call the - interactive pdb debugger after the traceback printout. %pdb toggles - this feature on and off. - - The initial state of this feature is set in your configuration - file (the option is ``InteractiveShell.pdb``). - - If you want to just activate the debugger AFTER an exception has fired, - without having to type '%pdb on' and rerunning your code, you can use - the %debug magic.""" - - par = parameter_s.strip().lower() - - if par: - try: - new_pdb = {'off':0,'0':0,'on':1,'1':1}[par] - except KeyError: - print ('Incorrect argument. Use on/1, off/0, ' - 'or nothing for a toggle.') - return - else: - # toggle - new_pdb = not self.shell.call_pdb - - # set on the shell - self.shell.call_pdb = new_pdb - print('Automatic pdb calling has been turned',on_off(new_pdb)) - - @magic_arguments.magic_arguments() - @magic_arguments.argument('--breakpoint', '-b', metavar='FILE:LINE', - help=""" - Set break point at LINE in FILE. - """ - ) - @magic_arguments.argument('statement', nargs='*', - help=""" - Code to run in debugger. - You can omit this in cell magic mode. - """ - ) - @no_var_expand - @line_cell_magic - def debug(self, line='', cell=None): - """Activate the interactive debugger. - - This magic command support two ways of activating debugger. - One is to activate debugger before executing code. This way, you - can set a break point, to step through the code from the point. - You can use this mode by giving statements to execute and optionally - a breakpoint. - - The other one is to activate debugger in post-mortem mode. You can - activate this mode simply running %debug without any argument. - If an exception has just occurred, this lets you inspect its stack - frames interactively. Note that this will always work only on the last - traceback that occurred, so you must call this quickly after an - exception that you wish to inspect has fired, because if another one - occurs, it clobbers the previous one. - - If you want IPython to automatically do this on every exception, see - the %pdb magic for more details. - - .. versionchanged:: 7.3 - When running code, user variables are no longer expanded, - the magic line is always left unmodified. - - """ - args = magic_arguments.parse_argstring(self.debug, line) - - if not (args.breakpoint or args.statement or cell): - self._debug_post_mortem() - elif not (args.breakpoint or cell): - # If there is no breakpoints, the line is just code to execute - self._debug_exec(line, None) - else: - # Here we try to reconstruct the code from the output of - # parse_argstring. This might not work if the code has spaces - # For example this fails for `print("a b")` - code = "\n".join(args.statement) - if cell: - code += "\n" + cell - self._debug_exec(code, args.breakpoint) - - def _debug_post_mortem(self): - self.shell.debugger(force=True) - - def _debug_exec(self, code, breakpoint): - if breakpoint: - (filename, bp_line) = breakpoint.rsplit(':', 1) - bp_line = int(bp_line) - else: - (filename, bp_line) = (None, None) - self._run_with_debugger(code, self.shell.user_ns, filename, bp_line) - - @line_magic - def tb(self, s): - """Print the last traceback. - - Optionally, specify an exception reporting mode, tuning the - verbosity of the traceback. By default the currently-active exception - mode is used. See %xmode for changing exception reporting modes. - - Valid modes: Plain, Context, Verbose, and Minimal. - """ - interactive_tb = self.shell.InteractiveTB - if s: - # Switch exception reporting mode for this one call. - # Ensure it is switched back. - def xmode_switch_err(name): - warn('Error changing %s exception modes.\n%s' % - (name,sys.exc_info()[1])) - - new_mode = s.strip().capitalize() - original_mode = interactive_tb.mode - try: - try: - interactive_tb.set_mode(mode=new_mode) - except Exception: - xmode_switch_err('user') - else: - self.shell.showtraceback() - finally: - interactive_tb.set_mode(mode=original_mode) - else: - self.shell.showtraceback() - - @skip_doctest - @line_magic - def run(self, parameter_s='', runner=None, - file_finder=get_py_filename): - """Run the named file inside IPython as a program. - - Usage:: - - %run [-n -i -e -G] - [( -t [-N<N>] | -d [-b<N>] | -p [profile options] )] - ( -m mod | filename ) [args] - - The filename argument should be either a pure Python script (with - extension ``.py``), or a file with custom IPython syntax (such as - magics). If the latter, the file can be either a script with ``.ipy`` - extension, or a Jupyter notebook with ``.ipynb`` extension. When running - a Jupyter notebook, the output from print statements and other - displayed objects will appear in the terminal (even matplotlib figures - will open, if a terminal-compliant backend is being used). Note that, - at the system command line, the ``jupyter run`` command offers similar - functionality for executing notebooks (albeit currently with some - differences in supported options). - - Parameters after the filename are passed as command-line arguments to - the program (put in sys.argv). Then, control returns to IPython's - prompt. - - This is similar to running at a system prompt ``python file args``, - but with the advantage of giving you IPython's tracebacks, and of - loading all variables into your interactive namespace for further use - (unless -p is used, see below). - - The file is executed in a namespace initially consisting only of - ``__name__=='__main__'`` and sys.argv constructed as indicated. It thus - sees its environment as if it were being run as a stand-alone program - (except for sharing global objects such as previously imported - modules). But after execution, the IPython interactive namespace gets - updated with all variables defined in the program (except for __name__ - and sys.argv). This allows for very convenient loading of code for - interactive work, while giving each program a 'clean sheet' to run in. - - Arguments are expanded using shell-like glob match. Patterns - '*', '?', '[seq]' and '[!seq]' can be used. Additionally, - tilde '~' will be expanded into user's home directory. Unlike - real shells, quotation does not suppress expansions. Use - *two* back slashes (e.g. ``\\\\*``) to suppress expansions. - To completely disable these expansions, you can use -G flag. - - On Windows systems, the use of single quotes `'` when specifying - a file is not supported. Use double quotes `"`. - - Options: - - -n - __name__ is NOT set to '__main__', but to the running file's name - without extension (as python does under import). This allows running - scripts and reloading the definitions in them without calling code - protected by an ``if __name__ == "__main__"`` clause. - - -i - run the file in IPython's namespace instead of an empty one. This - is useful if you are experimenting with code written in a text editor - which depends on variables defined interactively. - - -e - ignore sys.exit() calls or SystemExit exceptions in the script - being run. This is particularly useful if IPython is being used to - run unittests, which always exit with a sys.exit() call. In such - cases you are interested in the output of the test results, not in - seeing a traceback of the unittest module. - - -t - print timing information at the end of the run. IPython will give - you an estimated CPU time consumption for your script, which under - Unix uses the resource module to avoid the wraparound problems of - time.clock(). Under Unix, an estimate of time spent on system tasks - is also given (for Windows platforms this is reported as 0.0). - - If -t is given, an additional ``-N<N>`` option can be given, where <N> - must be an integer indicating how many times you want the script to - run. The final timing report will include total and per run results. - - For example (testing the script uniq_stable.py):: - - In [1]: run -t uniq_stable - - IPython CPU timings (estimated): - User : 0.19597 s. - System: 0.0 s. - - In [2]: run -t -N5 uniq_stable - - IPython CPU timings (estimated): - Total runs performed: 5 - Times : Total Per run - User : 0.910862 s, 0.1821724 s. - System: 0.0 s, 0.0 s. - - -d - run your program under the control of pdb, the Python debugger. - This allows you to execute your program step by step, watch variables, - etc. Internally, what IPython does is similar to calling:: - - pdb.run('execfile("YOURFILENAME")') - - with a breakpoint set on line 1 of your file. You can change the line - number for this automatic breakpoint to be <N> by using the -bN option - (where N must be an integer). For example:: - - %run -d -b40 myscript - - will set the first breakpoint at line 40 in myscript.py. Note that - the first breakpoint must be set on a line which actually does - something (not a comment or docstring) for it to stop execution. - - Or you can specify a breakpoint in a different file:: - - %run -d -b myotherfile.py:20 myscript - - When the pdb debugger starts, you will see a (Pdb) prompt. You must - first enter 'c' (without quotes) to start execution up to the first - breakpoint. - - Entering 'help' gives information about the use of the debugger. You - can easily see pdb's full documentation with "import pdb;pdb.help()" - at a prompt. - - -p - run program under the control of the Python profiler module (which - prints a detailed report of execution times, function calls, etc). - - You can pass other options after -p which affect the behavior of the - profiler itself. See the docs for %prun for details. - - In this mode, the program's variables do NOT propagate back to the - IPython interactive namespace (because they remain in the namespace - where the profiler executes them). - - Internally this triggers a call to %prun, see its documentation for - details on the options available specifically for profiling. - - There is one special usage for which the text above doesn't apply: - if the filename ends with .ipy[nb], the file is run as ipython script, - just as if the commands were written on IPython prompt. - - -m - specify module name to load instead of script path. Similar to - the -m option for the python interpreter. Use this option last if you - want to combine with other %run options. Unlike the python interpreter - only source modules are allowed no .pyc or .pyo files. - For example:: - - %run -m example - - will run the example module. - - -G - disable shell-like glob expansion of arguments. - - """ - - # Logic to handle issue #3664 - # Add '--' after '-m <module_name>' to ignore additional args passed to a module. - if '-m' in parameter_s and '--' not in parameter_s: - argv = shlex.split(parameter_s, posix=(os.name == 'posix')) - for idx, arg in enumerate(argv): - if arg and arg.startswith('-') and arg != '-': - if arg == '-m': - argv.insert(idx + 2, '--') - break - else: - # Positional arg, break - break - parameter_s = ' '.join(shlex.quote(arg) for arg in argv) - - # get arguments and set sys.argv for program to be run. - opts, arg_lst = self.parse_options(parameter_s, - 'nidtN:b:pD:l:rs:T:em:G', - mode='list', list_all=1) - if "m" in opts: - modulename = opts["m"][0] - modpath = find_mod(modulename) - if modpath is None: - msg = '%r is not a valid modulename on sys.path'%modulename - raise Exception(msg) - arg_lst = [modpath] + arg_lst - try: - fpath = None # initialize to make sure fpath is in scope later - fpath = arg_lst[0] - filename = file_finder(fpath) - except IndexError as e: - msg = 'you must provide at least a filename.' - raise Exception(msg) from e - except IOError as e: - try: - msg = str(e) - except UnicodeError: - msg = e.message - if os.name == 'nt' and re.match(r"^'.*'$",fpath): - warn('For Windows, use double quotes to wrap a filename: %run "mypath\\myfile.py"') - raise Exception(msg) from e - except TypeError: - if fpath in sys.meta_path: - filename = "" - else: - raise - - if filename.lower().endswith(('.ipy', '.ipynb')): - with preserve_keys(self.shell.user_ns, '__file__'): - self.shell.user_ns['__file__'] = filename - self.shell.safe_execfile_ipy(filename, raise_exceptions=True) - return - - # Control the response to exit() calls made by the script being run - exit_ignore = 'e' in opts - - # Make sure that the running script gets a proper sys.argv as if it - # were run from a system shell. - save_argv = sys.argv # save it for later restoring - - if 'G' in opts: - args = arg_lst[1:] - else: - # tilde and glob expansion - args = shellglob(map(os.path.expanduser, arg_lst[1:])) - - sys.argv = [filename] + args # put in the proper filename - - if 'n' in opts: - name = Path(filename).stem - else: - name = '__main__' - - if 'i' in opts: - # Run in user's interactive namespace - prog_ns = self.shell.user_ns - __name__save = self.shell.user_ns['__name__'] - prog_ns['__name__'] = name - main_mod = self.shell.user_module - - # Since '%run foo' emulates 'python foo.py' at the cmd line, we must - # set the __file__ global in the script's namespace - # TK: Is this necessary in interactive mode? - prog_ns['__file__'] = filename - else: - # Run in a fresh, empty namespace - - # The shell MUST hold a reference to prog_ns so after %run - # exits, the python deletion mechanism doesn't zero it out - # (leaving dangling references). See interactiveshell for details - main_mod = self.shell.new_main_mod(filename, name) - prog_ns = main_mod.__dict__ - - # pickle fix. See interactiveshell for an explanation. But we need to - # make sure that, if we overwrite __main__, we replace it at the end - main_mod_name = prog_ns['__name__'] - - if main_mod_name == '__main__': - restore_main = sys.modules['__main__'] - else: - restore_main = False - - # This needs to be undone at the end to prevent holding references to - # every single object ever created. - sys.modules[main_mod_name] = main_mod - - if 'p' in opts or 'd' in opts: - if 'm' in opts: - code = 'run_module(modulename, prog_ns)' - code_ns = { - 'run_module': self.shell.safe_run_module, - 'prog_ns': prog_ns, - 'modulename': modulename, - } - else: - if 'd' in opts: - # allow exceptions to raise in debug mode - code = 'execfile(filename, prog_ns, raise_exceptions=True)' - else: - code = 'execfile(filename, prog_ns)' - code_ns = { - 'execfile': self.shell.safe_execfile, - 'prog_ns': prog_ns, - 'filename': get_py_filename(filename), - } - - 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) - else: - 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) - 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 - # %run. As best I can see, this is NOT something IPython is doing - # at all, and similar problems have been reported before: - # http://coding.derkeiler.com/Archive/Python/comp.lang.python/2004-10/0188.html - # Since this seems to be done by the interpreter itself, the best - # we can do is to at least restore __builtins__ for the user on - # exit. - self.shell.user_ns['__builtins__'] = builtin_mod - - # Ensure key global structures are restored - sys.argv = save_argv - if restore_main: - sys.modules['__main__'] = restore_main - if '__mp_main__' in sys.modules: - sys.modules['__mp_main__'] = restore_main - else: - # Remove from sys.modules the reference to main_mod we'd - # added. Otherwise it will trap references to objects - # contained therein. - del sys.modules[main_mod_name] - - return stats - - def _run_with_debugger(self, code, code_ns, filename=None, - bp_line=None, bp_file=None): - """ - Run `code` in debugger with a break point. - - Parameters - ---------- - code : str - Code to execute. - code_ns : dict - A namespace in which `code` is executed. - filename : str - `code` is ran as if it is in `filename`. - bp_line : int, optional - Line number of the break point. - bp_file : str, optional - Path to the file in which break point is specified. - `filename` is used if not given. - - Raises - ------ - UsageError - 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.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'): - del deb.curframe - - # reset Breakpoint state, which is moronically kept - # in a class - bdb.Breakpoint.next = 1 - bdb.Breakpoint.bplist = {} - bdb.Breakpoint.bpbynumber = [None] - deb.clear_all_breaks() - if bp_line is not None: - # Set an initial breakpoint to stop execution - maxtries = 10 - bp_file = bp_file or filename - checkline = deb.checkline(bp_file, bp_line) - if not checkline: - for bp in range(bp_line + 1, bp_line + maxtries + 1): - if deb.checkline(bp_file, bp): - break - else: - msg = ("\nI failed to find a valid line to set " - "a breakpoint\n" - "after trying up to line: %s.\n" - "Please set a valid breakpoint manually " - "with the -b option." % bp) - raise UsageError(msg) - # if we find a good linenumber, set the breakpoint - deb.do_break('%s:%s' % (bp_file, bp_line)) - - if filename: - # Mimic Pdb._runscript(...) - deb._wait_for_mainpyfile = True - deb.mainpyfile = deb.canonic(filename) - - # Start file run - print("NOTE: Enter 'c' at the %s prompt to continue execution." % deb.prompt) - try: - if filename: - # save filename so it can be used by methods on the deb object - deb._exec_filename = filename - while True: - try: - trace = sys.gettrace() - deb.run(code, code_ns) - except Restart: - print("Restarting") - if filename: - deb._wait_for_mainpyfile = True - deb.mainpyfile = deb.canonic(filename) - continue - else: - break - finally: - sys.settrace(trace) - - - except: - etype, value, tb = sys.exc_info() - # Skip three frames in the traceback: the %run one, - # one inside bdb.py, and the command-line typed by the - # user (run by exec in pdb itself). - self.shell.InteractiveTB(etype, value, tb, tb_offset=3) - - @staticmethod - def _run_with_timing(run, nruns): - """ - Run function `run` and print timing information. - - Parameters - ---------- - run : callable - Any callable object which takes no argument. - nruns : int - Number of times to execute `run`. - - """ - twall0 = time.perf_counter() - if nruns == 1: - t0 = clock2() - run() - t1 = clock2() - t_usr = t1[0] - t0[0] - t_sys = t1[1] - t0[1] - print("\nIPython CPU timings (estimated):") - print(" User : %10.2f s." % t_usr) - print(" System : %10.2f s." % t_sys) - else: - runs = range(nruns) - t0 = clock2() - for nr in runs: - run() - t1 = clock2() - t_usr = t1[0] - t0[0] - t_sys = t1[1] - t0[1] - print("\nIPython CPU timings (estimated):") - print("Total runs performed:", nruns) - print(" Times : %10s %10s" % ('Total', 'Per run')) - print(" User : %10.2f s, %10.2f s." % (t_usr, t_usr / nruns)) - print(" System : %10.2f s, %10.2f s." % (t_sys, t_sys / nruns)) - twall1 = time.perf_counter() - print("Wall time: %10.2f s." % (twall1 - twall0)) - - @skip_doctest - @no_var_expand - @line_cell_magic - @needs_local_scope - def timeit(self, line='', cell=None, local_ns=None): - """Time execution of a Python statement or expression - - Usage, in line mode: - %timeit [-n<N> -r<R> [-t|-c] -q -p<P> -o] statement - or in cell mode: - %%timeit [-n<N> -r<R> [-t|-c] -q -p<P> -o] setup_code - code - code... - - Time execution of a Python statement or expression using the timeit - module. This function can be used both as a line and cell magic: - - - In line mode you can time a single-line statement (though multiple - ones can be chained with using semicolons). - - - In cell mode, the statement in the first line is used as setup code - (executed but not timed) and the body of the cell is timed. The cell - body has access to any variables created in the setup code. - - Options: - -n<N>: execute the given statement <N> times in a loop. If <N> is not - provided, <N> is determined so as to get sufficient accuracy. - - -r<R>: number of repeats <R>, each consisting of <N> loops, and take the - best result. - Default: 7 - - -t: use time.time to measure the time, which is the default on Unix. - This function measures wall time. - - -c: use time.clock to measure the time, which is the default on - Windows and measures wall time. On Unix, resource.getrusage is used - instead and returns the CPU user time. - - -p<P>: use a precision of <P> digits to display the timing result. - Default: 3 - - -q: Quiet, do not print result. - - -o: return a TimeitResult that can be stored in a variable to inspect - the result in more details. - - .. versionchanged:: 7.3 - User variables are no longer expanded, - the magic line is always left unmodified. - - Examples - -------- - :: - - In [1]: %timeit pass - 8.26 ns ± 0.12 ns per loop (mean ± std. dev. of 7 runs, 100000000 loops each) - - In [2]: u = None - - In [3]: %timeit u is None - 29.9 ns ± 0.643 ns per loop (mean ± std. dev. of 7 runs, 10000000 loops each) - - In [4]: %timeit -r 4 u == None - - In [5]: import time - - In [6]: %timeit -n1 time.sleep(2) - - The times reported by %timeit will be slightly higher than those - reported by the timeit.py script when variables are accessed. This is - due to the fact that %timeit executes the statement in the namespace - of the shell, compared with timeit.py, which uses a single setup - statement to import function or create variables. Generally, the bias - does not matter as long as results from timeit.py are not mixed with - those from %timeit.""" - - opts, stmt = self.parse_options( - line, "n:r:tcp:qo", posix=False, strict=False, preserve_non_opts=True - ) - if stmt == "" and cell is None: - return - - timefunc = timeit.default_timer - number = int(getattr(opts, "n", 0)) - default_repeat = 7 if timeit.default_repeat < 7 else timeit.default_repeat - repeat = int(getattr(opts, "r", default_repeat)) - precision = int(getattr(opts, "p", 3)) - quiet = 'q' in opts - return_result = 'o' in opts - if hasattr(opts, "t"): - timefunc = time.time - if hasattr(opts, "c"): - timefunc = clock - - timer = Timer(timer=timefunc) - # this code has tight coupling to the inner workings of timeit.Timer, - # but is there a better way to achieve that the code stmt has access - # to the shell namespace? - transform = self.shell.transform_cell - - if cell is None: - # called as line magic - ast_setup = self.shell.compile.ast_parse("pass") - ast_stmt = self.shell.compile.ast_parse(transform(stmt)) - else: - ast_setup = self.shell.compile.ast_parse(transform(stmt)) - ast_stmt = self.shell.compile.ast_parse(transform(cell)) - - ast_setup = self.shell.transform_ast(ast_setup) - ast_stmt = self.shell.transform_ast(ast_stmt) - - # Check that these compile to valid Python code *outside* the timer func - # Invalid code may become valid when put inside the function & loop, - # which messes up error messages. - # https://github.com/ipython/ipython/issues/10636 - self.shell.compile(ast_setup, "<magic-timeit-setup>", "exec") - self.shell.compile(ast_stmt, "<magic-timeit-stmt>", "exec") - - # This codestring is taken from timeit.template - we fill it in as an - # AST, so that we can apply our AST transformations to the user code - # without affecting the timing code. - timeit_ast_template = ast.parse('def inner(_it, _timer):\n' - ' setup\n' - ' _t0 = _timer()\n' - ' for _i in _it:\n' - ' stmt\n' - ' _t1 = _timer()\n' - ' return _t1 - _t0\n') - - timeit_ast = TimeitTemplateFiller(ast_setup, ast_stmt).visit(timeit_ast_template) - timeit_ast = ast.fix_missing_locations(timeit_ast) - - # Track compilation time so it can be reported if too long - # Minimum time above which compilation time will be reported - tc_min = 0.1 - - t0 = clock() - code = self.shell.compile(timeit_ast, "<magic-timeit>", "exec") - tc = clock()-t0 - - ns = {} - glob = self.shell.user_ns - # handles global vars with same name as local vars. We store them in conflict_globs. - conflict_globs = {} - if local_ns and cell is None: - for var_name, var_val in glob.items(): - if var_name in local_ns: - conflict_globs[var_name] = var_val - glob.update(local_ns) - - exec(code, glob, ns) - timer.inner = ns["inner"] - - # This is used to check if there is a huge difference between the - # best and worst timings. - # Issue: https://github.com/ipython/ipython/issues/6471 - if number == 0: - # determine number so that 0.2 <= total time < 2.0 - for index in range(0, 10): - number = 10 ** index - time_number = timer.timeit(number) - if time_number >= 0.2: - break - - all_runs = timer.repeat(repeat, number) - best = min(all_runs) / number - worst = max(all_runs) / number - timeit_result = TimeitResult(number, repeat, best, worst, all_runs, tc, precision) - - # Restore global vars from conflict_globs - if conflict_globs: - glob.update(conflict_globs) - - if not quiet : - # Check best timing is greater than zero to avoid a - # ZeroDivisionError. - # In cases where the slowest timing is lesser than a microsecond - # we assume that it does not really matter if the fastest - # timing is 4 times faster than the slowest timing or not. - if worst > 4 * best and best > 0 and worst > 1e-6: - print("The slowest run took %0.2f times longer than the " - "fastest. This could mean that an intermediate result " - "is being cached." % (worst / best)) - - print( timeit_result ) - - if tc > tc_min: - print("Compiler time: %.2f s" % tc) - if return_result: - return timeit_result - - @skip_doctest - @no_var_expand - @needs_local_scope - @line_cell_magic - def time(self,line='', cell=None, local_ns=None): - """Time execution of a Python statement or expression. - - The CPU and wall clock times are printed, and the value of the - expression (if any) is returned. Note that under Win32, system time - is always reported as 0, since it can not be measured. - - This function can be used both as a line and cell magic: - - - In line mode you can time a single-line statement (though multiple - ones can be chained with using semicolons). - - - In cell mode, you can time the cell body (a directly - following statement raises an error). - - This function provides very basic timing functionality. Use the timeit - magic for more control over the measurement. - - .. versionchanged:: 7.3 - User variables are no longer expanded, - the magic line is always left unmodified. - - Examples - -------- - :: - - In [1]: %time 2**128 - CPU times: user 0.00 s, sys: 0.00 s, total: 0.00 s - Wall time: 0.00 - Out[1]: 340282366920938463463374607431768211456L - - In [2]: n = 1000000 - - In [3]: %time sum(range(n)) - CPU times: user 1.20 s, sys: 0.05 s, total: 1.25 s - Wall time: 1.37 - Out[3]: 499999500000L - - In [4]: %time print 'hello world' - hello world - CPU times: user 0.00 s, sys: 0.00 s, total: 0.00 s - Wall time: 0.00 - - .. note:: - The time needed by Python to compile the given expression will be - reported if it is more than 0.1s. - - In the example below, the actual exponentiation is done by Python - at compilation time, so while the expression can take a noticeable - amount of time to compute, that time is purely due to the - compilation:: - - In [5]: %time 3**9999; - CPU times: user 0.00 s, sys: 0.00 s, total: 0.00 s - Wall time: 0.00 s - - In [6]: %time 3**999999; - CPU times: user 0.00 s, sys: 0.00 s, total: 0.00 s - Wall time: 0.00 s - Compiler : 0.78 s - """ - # fail immediately if the given expression can't be compiled - - if line and cell: - raise UsageError("Can't use statement directly after '%%time'!") - - if cell: - expr = self.shell.transform_cell(cell) - else: - expr = self.shell.transform_cell(line) - - # Minimum time above which parse time will be reported - tp_min = 0.1 - - t0 = clock() - expr_ast = self.shell.compile.ast_parse(expr) - tp = clock()-t0 - - # Apply AST transformations - expr_ast = self.shell.transform_ast(expr_ast) - - # Minimum time above which compilation time will be reported - tc_min = 0.1 - - expr_val=None - if len(expr_ast.body)==1 and isinstance(expr_ast.body[0], ast.Expr): - mode = 'eval' - source = '<timed eval>' - expr_ast = ast.Expression(expr_ast.body[0].value) - else: - mode = 'exec' - source = '<timed exec>' - # multi-line %%time case - if len(expr_ast.body) > 1 and isinstance(expr_ast.body[-1], ast.Expr): - expr_val= expr_ast.body[-1] - expr_ast = expr_ast.body[:-1] - expr_ast = Module(expr_ast, []) - expr_val = ast.Expression(expr_val.value) - - t0 = clock() - code = self.shell.compile(expr_ast, source, mode) - tc = clock()-t0 - - # skew measurement as little as possible - glob = self.shell.user_ns - wtime = time.time - # time execution - wall_st = wtime() - if mode=='eval': - st = clock2() - try: - out = eval(code, glob, local_ns) - except: - self.shell.showtraceback() - return - end = clock2() - else: - st = clock2() - try: - exec(code, glob, local_ns) - out=None - # multi-line %%time case - if expr_val is not None: - code_2 = self.shell.compile(expr_val, source, 'eval') - out = eval(code_2, glob, local_ns) - except: - self.shell.showtraceback() - return - end = clock2() - - wall_end = wtime() - # Compute actual times and report - wall_time = wall_end - wall_st - cpu_user = end[0] - st[0] - cpu_sys = end[1] - st[1] - cpu_tot = cpu_user + cpu_sys - # On windows cpu_sys is always zero, so only total is displayed - if sys.platform != "win32": - print( - f"CPU times: user {_format_time(cpu_user)}, sys: {_format_time(cpu_sys)}, total: {_format_time(cpu_tot)}" - ) - else: - print(f"CPU times: total: {_format_time(cpu_tot)}") - print(f"Wall time: {_format_time(wall_time)}") - if tc > tc_min: - print(f"Compiler : {_format_time(tc)}") - if tp > tp_min: - print(f"Parser : {_format_time(tp)}") - return out - - @skip_doctest - @line_magic - def macro(self, parameter_s=''): - """Define a macro for future re-execution. It accepts ranges of history, - filenames or string objects. - - Usage:\\ - %macro [options] name n1-n2 n3-n4 ... n5 .. n6 ... - - Options: - - -r: use 'raw' input. By default, the 'processed' history is used, - so that magics are loaded in their transformed version to valid - Python. If this option is given, the raw input as typed at the - command line is used instead. - - -q: quiet macro definition. By default, a tag line is printed - to indicate the macro has been created, and then the contents of - the macro are printed. If this option is given, then no printout - is produced once the macro is created. - - This will define a global variable called `name` which is a string - made of joining the slices and lines you specify (n1,n2,... numbers - above) from your input history into a single string. This variable - acts like an automatic function which re-executes those lines as if - you had typed them. You just type 'name' at the prompt and the code - executes. - - The syntax for indicating input ranges is described in %history. - - Note: as a 'hidden' feature, you can also use traditional python slice - notation, where N:M means numbers N through M-1. - - For example, if your history contains (print using %hist -n ):: - - 44: x=1 - 45: y=3 - 46: z=x+y - 47: print x - 48: a=5 - 49: print 'x',x,'y',y - - you can create a macro with lines 44 through 47 (included) and line 49 - called my_macro with:: - - In [55]: %macro my_macro 44-47 49 - - Now, typing `my_macro` (without quotes) will re-execute all this code - in one pass. - - You don't need to give the line-numbers in order, and any given line - number can appear multiple times. You can assemble macros with any - lines from your input history in any order. - - The macro is a simple object which holds its value in an attribute, - but IPython's display system checks for macros and executes them as - code instead of printing them when you type their name. - - You can view a macro's contents by explicitly printing it with:: - - print macro_name - - """ - opts,args = self.parse_options(parameter_s,'rq',mode='list') - if not args: # List existing macros - return sorted(k for k,v in self.shell.user_ns.items() if isinstance(v, Macro)) - if len(args) == 1: - raise UsageError( - "%macro insufficient args; usage '%macro name n1-n2 n3-4...") - name, codefrom = args[0], " ".join(args[1:]) - - #print 'rng',ranges # dbg - try: - lines = self.shell.find_user_code(codefrom, 'r' in opts) - except (ValueError, TypeError) as e: - print(e.args[0]) - return - macro = Macro(lines) - self.shell.define_macro(name, macro) - if not ( 'q' in opts) : - print('Macro `%s` created. To execute, type its name (without quotes).' % name) - print('=== Macro contents: ===') - print(macro, end=' ') - - @magic_arguments.magic_arguments() - @magic_arguments.argument('output', type=str, default='', nargs='?', - help="""The name of the variable in which to store output. - This is a utils.io.CapturedIO object with stdout/err attributes - for the text of the captured output. - - CapturedOutput also has a show() method for displaying the output, - and __call__ as well, so you can use that to quickly display the - output. - - If unspecified, captured output is discarded. - """ - ) - @magic_arguments.argument('--no-stderr', action="store_true", - help="""Don't capture stderr.""" - ) - @magic_arguments.argument('--no-stdout', action="store_true", - help="""Don't capture stdout.""" - ) - @magic_arguments.argument('--no-display', action="store_true", - help="""Don't capture IPython's rich display.""" - ) - @cell_magic - def capture(self, line, cell): - """run the cell, capturing stdout, stderr, and IPython's rich display() calls.""" - args = magic_arguments.parse_argstring(self.capture, line) - out = not args.no_stdout - err = not args.no_stderr - disp = not args.no_display - with capture_output(out, err, disp) as io: - self.shell.run_cell(cell) - if args.output: - self.shell.user_ns[args.output] = io - -def parse_breakpoint(text, current_file): - '''Returns (file, line) for file:line and (current_file, line) for line''' - colon = text.find(':') - if colon == -1: - return current_file, int(text) - else: - return text[:colon], int(text[colon+1:]) - -def _format_time(timespan, precision=3): - """Formats the timespan in a human readable form""" - - if timespan >= 60.0: - # we have more than a minute, format that in a human readable form - # Idea from http://snipplr.com/view/5713/ - parts = [("d", 60*60*24),("h", 60*60),("min", 60), ("s", 1)] - time = [] - leftover = timespan - for suffix, length in parts: - value = int(leftover / length) - if value > 0: - leftover = leftover % length - time.append(u'%s%s' % (str(value), suffix)) - if leftover < 1: - break - return " ".join(time) - - - # Unfortunately the unicode 'micro' symbol can cause problems in - # certain terminals. - # See bug: https://bugs.launchpad.net/ipython/+bug/348466 - # Try to prevent crashes by being more secure than it needs to - # E.g. eclipse is able to print a µ, but has no sys.stdout.encoding set. - units = [u"s", u"ms",u'us',"ns"] # the save value - if hasattr(sys.stdout, 'encoding') and sys.stdout.encoding: - try: - u'\xb5'.encode(sys.stdout.encoding) - units = [u"s", u"ms",u'\xb5s',"ns"] - except: - pass - scaling = [1, 1e3, 1e6, 1e9] - - if timespan > 0.0: - order = min(-int(math.floor(math.log10(timespan)) // 3), 3) - else: - order = 3 - return u"%.*g %s" % (precision, timespan * scaling[order], units[order]) diff --git a/contrib/python/ipython/py3/IPython/core/magics/extension.py b/contrib/python/ipython/py3/IPython/core/magics/extension.py deleted file mode 100644 index 2bc76b2d55..0000000000 --- a/contrib/python/ipython/py3/IPython/core/magics/extension.py +++ /dev/null @@ -1,63 +0,0 @@ -"""Implementation of magic functions for the extension machinery. -""" -#----------------------------------------------------------------------------- -# Copyright (c) 2012 The IPython Development Team. -# -# Distributed under the terms of the Modified BSD License. -# -# The full license is in the file COPYING.txt, distributed with this software. -#----------------------------------------------------------------------------- - -#----------------------------------------------------------------------------- -# Imports -#----------------------------------------------------------------------------- - - -# Our own packages -from IPython.core.error import UsageError -from IPython.core.magic import Magics, magics_class, line_magic - -#----------------------------------------------------------------------------- -# Magic implementation classes -#----------------------------------------------------------------------------- - -@magics_class -class ExtensionMagics(Magics): - """Magics to manage the IPython extensions system.""" - - @line_magic - def load_ext(self, module_str): - """Load an IPython extension by its module name.""" - if not module_str: - raise UsageError('Missing module name.') - res = self.shell.extension_manager.load_extension(module_str) - - if res == 'already loaded': - print("The %s extension is already loaded. To reload it, use:" % module_str) - print(" %reload_ext", module_str) - elif res == 'no load function': - print("The %s module is not an IPython extension." % module_str) - - @line_magic - def unload_ext(self, module_str): - """Unload an IPython extension by its module name. - - Not all extensions can be unloaded, only those which define an - ``unload_ipython_extension`` function. - """ - if not module_str: - raise UsageError('Missing module name.') - - res = self.shell.extension_manager.unload_extension(module_str) - - if res == 'no unload function': - print("The %s extension doesn't define how to unload it." % module_str) - elif res == "not loaded": - print("The %s extension is not loaded." % module_str) - - @line_magic - def reload_ext(self, module_str): - """Reload an IPython extension by its module name.""" - if not module_str: - raise UsageError('Missing module name.') - self.shell.extension_manager.reload_extension(module_str) diff --git a/contrib/python/ipython/py3/IPython/core/magics/history.py b/contrib/python/ipython/py3/IPython/core/magics/history.py deleted file mode 100644 index faa4335faa..0000000000 --- a/contrib/python/ipython/py3/IPython/core/magics/history.py +++ /dev/null @@ -1,338 +0,0 @@ -"""Implementation of magic functions related to History. -""" -#----------------------------------------------------------------------------- -# Copyright (c) 2012, IPython Development Team. -# -# Distributed under the terms of the Modified BSD License. -# -# The full license is in the file COPYING.txt, distributed with this software. -#----------------------------------------------------------------------------- - -#----------------------------------------------------------------------------- -# Imports -#----------------------------------------------------------------------------- - -# Stdlib -import os -import sys -from io import open as io_open -import fnmatch - -# Our own packages -from IPython.core.error import StdinNotImplementedError -from IPython.core.magic import Magics, magics_class, line_magic -from IPython.core.magic_arguments import (argument, magic_arguments, - parse_argstring) -from IPython.testing.skipdoctest import skip_doctest -from IPython.utils import io - -#----------------------------------------------------------------------------- -# Magics class implementation -#----------------------------------------------------------------------------- - - -_unspecified = object() - - -@magics_class -class HistoryMagics(Magics): - - @magic_arguments() - @argument( - '-n', dest='print_nums', action='store_true', default=False, - help=""" - print line numbers for each input. - This feature is only available if numbered prompts are in use. - """) - @argument( - '-o', dest='get_output', action='store_true', default=False, - help="also print outputs for each input.") - @argument( - '-p', dest='pyprompts', action='store_true', default=False, - help=""" - print classic '>>>' python prompts before each input. - This is useful for making documentation, and in conjunction - with -o, for producing doctest-ready output. - """) - @argument( - '-t', dest='raw', action='store_false', default=True, - help=""" - print the 'translated' history, as IPython understands it. - IPython filters your input and converts it all into valid Python - source before executing it (things like magics or aliases are turned - into function calls, for example). With this option, you'll see the - native history instead of the user-entered version: '%%cd /' will be - seen as 'get_ipython().run_line_magic("cd", "/")' instead of '%%cd /'. - """) - @argument( - '-f', dest='filename', - help=""" - FILENAME: instead of printing the output to the screen, redirect - it to the given file. The file is always overwritten, though *when - it can*, IPython asks for confirmation first. In particular, running - the command 'history -f FILENAME' from the IPython Notebook - interface will replace FILENAME even if it already exists *without* - confirmation. - """) - @argument( - '-g', dest='pattern', nargs='*', default=None, - help=""" - treat the arg as a glob pattern to search for in (full) history. - This includes the saved history (almost all commands ever written). - The pattern may contain '?' to match one unknown character and '*' - to match any number of unknown characters. Use '%%hist -g' to show - full saved history (may be very long). - """) - @argument( - '-l', dest='limit', type=int, nargs='?', default=_unspecified, - help=""" - get the last n lines from all sessions. Specify n as a single - arg, or the default is the last 10 lines. - """) - @argument( - '-u', dest='unique', action='store_true', - help=""" - when searching history using `-g`, show only unique history. - """) - @argument('range', nargs='*') - @skip_doctest - @line_magic - def history(self, parameter_s = ''): - """Print input history (_i<n> variables), with most recent last. - - By default, input history is printed without line numbers so it can be - directly pasted into an editor. Use -n to show them. - - By default, all input history from the current session is displayed. - Ranges of history can be indicated using the syntax: - - ``4`` - Line 4, current session - ``4-6`` - Lines 4-6, current session - ``243/1-5`` - Lines 1-5, session 243 - ``~2/7`` - Line 7, session 2 before current - ``~8/1-~6/5`` - From the first line of 8 sessions ago, to the fifth line of 6 - sessions ago. - - Multiple ranges can be entered, separated by spaces - - The same syntax is used by %macro, %save, %edit, %rerun - - Examples - -------- - :: - - In [6]: %history -n 4-6 - 4:a = 12 - 5:print a**2 - 6:%history -n 4-6 - - """ - - args = parse_argstring(self.history, parameter_s) - - # For brevity - history_manager = self.shell.history_manager - - def _format_lineno(session, line): - """Helper function to format line numbers properly.""" - if session in (0, history_manager.session_number): - return str(line) - return "%s/%s" % (session, line) - - # Check if output to specific file was requested. - outfname = args.filename - if not outfname: - outfile = sys.stdout # default - # We don't want to close stdout at the end! - close_at_end = False - else: - outfname = os.path.expanduser(outfname) - if os.path.exists(outfname): - try: - ans = io.ask_yes_no("File %r exists. Overwrite?" % outfname) - except StdinNotImplementedError: - ans = True - if not ans: - print('Aborting.') - return - print("Overwriting file.") - outfile = io_open(outfname, 'w', encoding='utf-8') - close_at_end = True - - print_nums = args.print_nums - get_output = args.get_output - pyprompts = args.pyprompts - raw = args.raw - - pattern = None - limit = None if args.limit is _unspecified else args.limit - - range_pattern = False - if args.pattern is not None and not args.range: - if args.pattern: - pattern = "*" + " ".join(args.pattern) + "*" - else: - pattern = "*" - hist = history_manager.search(pattern, raw=raw, output=get_output, - n=limit, unique=args.unique) - print_nums = True - elif args.limit is not _unspecified: - n = 10 if limit is None else limit - hist = history_manager.get_tail(n, raw=raw, output=get_output) - else: - if args.pattern: - range_pattern = "*" + " ".join(args.pattern) + "*" - print_nums = True - hist = history_manager.get_range_by_str( - " ".join(args.range), raw, get_output - ) - - # We could be displaying the entire history, so let's not try to pull - # it into a list in memory. Anything that needs more space will just - # misalign. - width = 4 - - for session, lineno, inline in hist: - # Print user history with tabs expanded to 4 spaces. The GUI - # clients use hard tabs for easier usability in auto-indented code, - # but we want to produce PEP-8 compliant history for safe pasting - # into an editor. - if get_output: - inline, output = inline - if range_pattern: - if not fnmatch.fnmatch(inline, range_pattern): - continue - inline = inline.expandtabs(4).rstrip() - - multiline = "\n" in inline - line_sep = '\n' if multiline else ' ' - if print_nums: - print(u'%s:%s' % (_format_lineno(session, lineno).rjust(width), - line_sep), file=outfile, end=u'') - if pyprompts: - print(u">>> ", end=u"", file=outfile) - if multiline: - inline = "\n... ".join(inline.splitlines()) + "\n..." - print(inline, file=outfile) - if get_output and output: - print(output, file=outfile) - - if close_at_end: - outfile.close() - - @line_magic - def recall(self, arg): - r"""Repeat a command, or get command to input line for editing. - - %recall and %rep are equivalent. - - - %recall (no arguments): - - Place a string version of last computation result (stored in the - special '_' variable) to the next input prompt. Allows you to create - elaborate command lines without using copy-paste:: - - In[1]: l = ["hei", "vaan"] - In[2]: "".join(l) - Out[2]: heivaan - In[3]: %recall - In[4]: heivaan_ <== cursor blinking - - %recall 45 - - Place history line 45 on the next input prompt. Use %hist to find - out the number. - - %recall 1-4 - - Combine the specified lines into one cell, and place it on the next - input prompt. See %history for the slice syntax. - - %recall foo+bar - - If foo+bar can be evaluated in the user namespace, the result is - placed at the next input prompt. Otherwise, the history is searched - for lines which contain that substring, and the most recent one is - placed at the next input prompt. - """ - if not arg: # Last output - self.shell.set_next_input(str(self.shell.user_ns["_"])) - return - # Get history range - histlines = self.shell.history_manager.get_range_by_str(arg) - cmd = "\n".join(x[2] for x in histlines) - if cmd: - self.shell.set_next_input(cmd.rstrip()) - return - - try: # Variable in user namespace - cmd = str(eval(arg, self.shell.user_ns)) - except Exception: # Search for term in history - histlines = self.shell.history_manager.search("*"+arg+"*") - for h in reversed([x[2] for x in histlines]): - if 'recall' in h or 'rep' in h: - continue - self.shell.set_next_input(h.rstrip()) - return - else: - self.shell.set_next_input(cmd.rstrip()) - return - print("Couldn't evaluate or find in history:", arg) - - @line_magic - def rerun(self, parameter_s=''): - """Re-run previous input - - By default, you can specify ranges of input history to be repeated - (as with %history). With no arguments, it will repeat the last line. - - Options: - - -l <n> : Repeat the last n lines of input, not including the - current command. - - -g foo : Repeat the most recent line which contains foo - """ - opts, args = self.parse_options(parameter_s, 'l:g:', mode='string') - if "l" in opts: # Last n lines - try: - n = int(opts["l"]) - except ValueError: - print("Number of lines must be an integer") - return - - if n == 0: - print("Requested 0 last lines - nothing to run") - return - elif n < 0: - print("Number of lines to rerun cannot be negative") - return - - hist = self.shell.history_manager.get_tail(n) - elif "g" in opts: # Search - p = "*"+opts['g']+"*" - hist = list(self.shell.history_manager.search(p)) - for l in reversed(hist): - if "rerun" not in l[2]: - hist = [l] # The last match which isn't a %rerun - break - else: - hist = [] # No matches except %rerun - elif args: # Specify history ranges - hist = self.shell.history_manager.get_range_by_str(args) - else: # Last line - hist = self.shell.history_manager.get_tail(1) - hist = [x[2] for x in hist] - if not hist: - print("No lines in history match specification") - return - histlines = "\n".join(hist) - print("=== Executing: ===") - print(histlines) - print("=== Output: ===") - self.shell.run_cell("\n".join(hist), store_history=False) diff --git a/contrib/python/ipython/py3/IPython/core/magics/logging.py b/contrib/python/ipython/py3/IPython/core/magics/logging.py deleted file mode 100644 index b6b8d8a5af..0000000000 --- a/contrib/python/ipython/py3/IPython/core/magics/logging.py +++ /dev/null @@ -1,195 +0,0 @@ -"""Implementation of magic functions for IPython's own logging. -""" -#----------------------------------------------------------------------------- -# Copyright (c) 2012 The IPython Development Team. -# -# Distributed under the terms of the Modified BSD License. -# -# The full license is in the file COPYING.txt, distributed with this software. -#----------------------------------------------------------------------------- - -#----------------------------------------------------------------------------- -# Imports -#----------------------------------------------------------------------------- - -# Stdlib -import os -import sys - -# Our own packages -from IPython.core.magic import Magics, magics_class, line_magic -from warnings import warn -from traitlets import Bool - -#----------------------------------------------------------------------------- -# Magic implementation classes -#----------------------------------------------------------------------------- - -@magics_class -class LoggingMagics(Magics): - """Magics related to all logging machinery.""" - - quiet = Bool(False, help= - """ - Suppress output of log state when logging is enabled - """ - ).tag(config=True) - - @line_magic - def logstart(self, parameter_s=''): - """Start logging anywhere in a session. - - %logstart [-o|-r|-t|-q] [log_name [log_mode]] - - If no name is given, it defaults to a file named 'ipython_log.py' in your - current directory, in 'rotate' mode (see below). - - '%logstart name' saves to file 'name' in 'backup' mode. It saves your - history up to that point and then continues logging. - - %logstart takes a second optional parameter: logging mode. This can be one - of (note that the modes are given unquoted): - - append - Keep logging at the end of any existing file. - - backup - Rename any existing file to name~ and start name. - - global - Append to a single logfile in your home directory. - - over - Overwrite any existing log. - - rotate - Create rotating logs: name.1~, name.2~, etc. - - Options: - - -o - log also IPython's output. In this mode, all commands which - generate an Out[NN] prompt are recorded to the logfile, right after - their corresponding input line. The output lines are always - prepended with a '#[Out]# ' marker, so that the log remains valid - Python code. - - Since this marker is always the same, filtering only the output from - a log is very easy, using for example a simple awk call:: - - awk -F'#\\[Out\\]# ' '{if($2) {print $2}}' ipython_log.py - - -r - log 'raw' input. Normally, IPython's logs contain the processed - input, so that user lines are logged in their final form, converted - into valid Python. For example, %Exit is logged as - _ip.magic("Exit"). If the -r flag is given, all input is logged - exactly as typed, with no transformations applied. - - -t - put timestamps before each input line logged (these are put in - comments). - - -q - suppress output of logstate message when logging is invoked - """ - - opts,par = self.parse_options(parameter_s,'ortq') - log_output = 'o' in opts - log_raw_input = 'r' in opts - timestamp = 't' in opts - quiet = 'q' in opts - - logger = self.shell.logger - - # if no args are given, the defaults set in the logger constructor by - # ipython remain valid - if par: - try: - logfname,logmode = par.split() - except: - logfname = par - logmode = 'backup' - else: - logfname = logger.logfname - logmode = logger.logmode - # put logfname into rc struct as if it had been called on the command - # line, so it ends up saved in the log header Save it in case we need - # to restore it... - old_logfile = self.shell.logfile - if logfname: - logfname = os.path.expanduser(logfname) - self.shell.logfile = logfname - - loghead = u'# IPython log file\n\n' - try: - logger.logstart(logfname, loghead, logmode, log_output, timestamp, - log_raw_input) - except: - self.shell.logfile = old_logfile - warn("Couldn't start log: %s" % sys.exc_info()[1]) - else: - # log input history up to this point, optionally interleaving - # output if requested - - if timestamp: - # disable timestamping for the previous history, since we've - # lost those already (no time machine here). - logger.timestamp = False - - if log_raw_input: - input_hist = self.shell.history_manager.input_hist_raw - else: - input_hist = self.shell.history_manager.input_hist_parsed - - if log_output: - log_write = logger.log_write - output_hist = self.shell.history_manager.output_hist - for n in range(1,len(input_hist)-1): - log_write(input_hist[n].rstrip() + u'\n') - if n in output_hist: - log_write(repr(output_hist[n]),'output') - else: - logger.log_write(u'\n'.join(input_hist[1:])) - logger.log_write(u'\n') - if timestamp: - # re-enable timestamping - logger.timestamp = True - - if not (self.quiet or quiet): - print ('Activating auto-logging. ' - 'Current session state plus future input saved.') - logger.logstate() - - @line_magic - def logstop(self, parameter_s=''): - """Fully stop logging and close log file. - - In order to start logging again, a new %logstart call needs to be made, - possibly (though not necessarily) with a new filename, mode and other - options.""" - self.shell.logger.logstop() - - @line_magic - def logoff(self, parameter_s=''): - """Temporarily stop logging. - - You must have previously started logging.""" - self.shell.logger.switch_log(0) - - @line_magic - def logon(self, parameter_s=''): - """Restart logging. - - This function is for restarting logging which you've temporarily - stopped with %logoff. For starting logging for the first time, you - must use the %logstart function, which allows you to specify an - optional log filename.""" - - self.shell.logger.switch_log(1) - - @line_magic - def logstate(self, parameter_s=''): - """Print the status of the logging system.""" - - self.shell.logger.logstate() diff --git a/contrib/python/ipython/py3/IPython/core/magics/namespace.py b/contrib/python/ipython/py3/IPython/core/magics/namespace.py deleted file mode 100644 index c86d3de9b6..0000000000 --- a/contrib/python/ipython/py3/IPython/core/magics/namespace.py +++ /dev/null @@ -1,711 +0,0 @@ -"""Implementation of namespace-related magic functions. -""" -#----------------------------------------------------------------------------- -# Copyright (c) 2012 The IPython Development Team. -# -# Distributed under the terms of the Modified BSD License. -# -# The full license is in the file COPYING.txt, distributed with this software. -#----------------------------------------------------------------------------- - -#----------------------------------------------------------------------------- -# Imports -#----------------------------------------------------------------------------- - -# Stdlib -import gc -import re -import sys - -# Our own packages -from IPython.core import page -from IPython.core.error import StdinNotImplementedError, UsageError -from IPython.core.magic import Magics, magics_class, line_magic -from IPython.testing.skipdoctest import skip_doctest -from IPython.utils.encoding import DEFAULT_ENCODING -from IPython.utils.openpy import read_py_file -from IPython.utils.path import get_py_filename - -#----------------------------------------------------------------------------- -# Magic implementation classes -#----------------------------------------------------------------------------- - -@magics_class -class NamespaceMagics(Magics): - """Magics to manage various aspects of the user's namespace. - - These include listing variables, introspecting into them, etc. - """ - - @line_magic - def pinfo(self, parameter_s='', namespaces=None): - """Provide detailed information about an object. - - '%pinfo object' is just a synonym for object? or ?object.""" - - #print 'pinfo par: <%s>' % parameter_s # dbg - # detail_level: 0 -> obj? , 1 -> obj?? - detail_level = 0 - # We need to detect if we got called as 'pinfo pinfo foo', which can - # happen if the user types 'pinfo foo?' at the cmd line. - pinfo,qmark1,oname,qmark2 = \ - re.match(r'(pinfo )?(\?*)(.*?)(\??$)',parameter_s).groups() - if pinfo or qmark1 or qmark2: - detail_level = 1 - if "*" in oname: - self.psearch(oname) - else: - self.shell._inspect('pinfo', oname, detail_level=detail_level, - namespaces=namespaces) - - @line_magic - def pinfo2(self, parameter_s='', namespaces=None): - """Provide extra detailed information about an object. - - '%pinfo2 object' is just a synonym for object?? or ??object.""" - self.shell._inspect('pinfo', parameter_s, detail_level=1, - namespaces=namespaces) - - @skip_doctest - @line_magic - def pdef(self, parameter_s='', namespaces=None): - """Print the call signature for any callable object. - - If the object is a class, print the constructor information. - - Examples - -------- - :: - - In [3]: %pdef urllib.urlopen - urllib.urlopen(url, data=None, proxies=None) - """ - self.shell._inspect('pdef',parameter_s, namespaces) - - @line_magic - def pdoc(self, parameter_s='', namespaces=None): - """Print the docstring for an object. - - If the given object is a class, it will print both the class and the - constructor docstrings.""" - self.shell._inspect('pdoc',parameter_s, namespaces) - - @line_magic - def psource(self, parameter_s='', namespaces=None): - """Print (or run through pager) the source code for an object.""" - if not parameter_s: - raise UsageError('Missing object name.') - self.shell._inspect('psource',parameter_s, namespaces) - - @line_magic - def pfile(self, parameter_s='', namespaces=None): - """Print (or run through pager) the file where an object is defined. - - The file opens at the line where the object definition begins. IPython - will honor the environment variable PAGER if set, and otherwise will - do its best to print the file in a convenient form. - - If the given argument is not an object currently defined, IPython will - try to interpret it as a filename (automatically adding a .py extension - if needed). You can thus use %pfile as a syntax highlighting code - viewer.""" - - # first interpret argument as an object name - out = self.shell._inspect('pfile',parameter_s, namespaces) - # if not, try the input as a filename - if out == 'not found': - try: - filename = get_py_filename(parameter_s) - except IOError as msg: - print(msg) - return - page.page(self.shell.pycolorize(read_py_file(filename, skip_encoding_cookie=False))) - - @line_magic - def psearch(self, parameter_s=''): - """Search for object in namespaces by wildcard. - - %psearch [options] PATTERN [OBJECT TYPE] - - Note: ? can be used as a synonym for %psearch, at the beginning or at - the end: both a*? and ?a* are equivalent to '%psearch a*'. Still, the - rest of the command line must be unchanged (options come first), so - for example the following forms are equivalent - - %psearch -i a* function - -i a* function? - ?-i a* function - - Arguments: - - PATTERN - - where PATTERN is a string containing * as a wildcard similar to its - use in a shell. The pattern is matched in all namespaces on the - search path. By default objects starting with a single _ are not - matched, many IPython generated objects have a single - underscore. The default is case insensitive matching. Matching is - also done on the attributes of objects and not only on the objects - in a module. - - [OBJECT TYPE] - - Is the name of a python type from the types module. The name is - given in lowercase without the ending type, ex. StringType is - written string. By adding a type here only objects matching the - given type are matched. Using all here makes the pattern match all - types (this is the default). - - Options: - - -a: makes the pattern match even objects whose names start with a - single underscore. These names are normally omitted from the - search. - - -i/-c: make the pattern case insensitive/sensitive. If neither of - these options are given, the default is read from your configuration - file, with the option ``InteractiveShell.wildcards_case_sensitive``. - If this option is not specified in your configuration file, IPython's - internal default is to do a case sensitive search. - - -e/-s NAMESPACE: exclude/search a given namespace. The pattern you - specify can be searched in any of the following namespaces: - 'builtin', 'user', 'user_global','internal', 'alias', where - 'builtin' and 'user' are the search defaults. Note that you should - not use quotes when specifying namespaces. - - -l: List all available object types for object matching. This function - can be used without arguments. - - 'Builtin' contains the python module builtin, 'user' contains all - user data, 'alias' only contain the shell aliases and no python - objects, 'internal' contains objects used by IPython. The - 'user_global' namespace is only used by embedded IPython instances, - and it contains module-level globals. You can add namespaces to the - search with -s or exclude them with -e (these options can be given - more than once). - - Examples - -------- - :: - - %psearch a* -> objects beginning with an a - %psearch -e builtin a* -> objects NOT in the builtin space starting in a - %psearch a* function -> all functions beginning with an a - %psearch re.e* -> objects beginning with an e in module re - %psearch r*.e* -> objects that start with e in modules starting in r - %psearch r*.* string -> all strings in modules beginning with r - - Case sensitive search:: - - %psearch -c a* list all object beginning with lower case a - - Show objects beginning with a single _:: - - %psearch -a _* list objects beginning with a single underscore - - List available objects:: - - %psearch -l list all available object types - """ - # default namespaces to be searched - def_search = ['user_local', 'user_global', 'builtin'] - - # Process options/args - opts,args = self.parse_options(parameter_s,'cias:e:l',list_all=True) - opt = opts.get - shell = self.shell - psearch = shell.inspector.psearch - - # select list object types - list_types = False - if 'l' in opts: - list_types = True - - # select case options - if 'i' in opts: - ignore_case = True - elif 'c' in opts: - ignore_case = False - else: - ignore_case = not shell.wildcards_case_sensitive - - # Build list of namespaces to search from user options - def_search.extend(opt('s',[])) - ns_exclude = ns_exclude=opt('e',[]) - ns_search = [nm for nm in def_search if nm not in ns_exclude] - - # Call the actual search - try: - psearch(args,shell.ns_table,ns_search, - show_all=opt('a'),ignore_case=ignore_case, list_types=list_types) - except: - shell.showtraceback() - - @skip_doctest - @line_magic - def who_ls(self, parameter_s=''): - """Return a sorted list of all interactive variables. - - If arguments are given, only variables of types matching these - arguments are returned. - - Examples - -------- - Define two variables and list them with who_ls:: - - In [1]: alpha = 123 - - In [2]: beta = 'test' - - In [3]: %who_ls - Out[3]: ['alpha', 'beta'] - - In [4]: %who_ls int - Out[4]: ['alpha'] - - In [5]: %who_ls str - Out[5]: ['beta'] - """ - - user_ns = self.shell.user_ns - user_ns_hidden = self.shell.user_ns_hidden - nonmatching = object() # This can never be in user_ns - out = [ i for i in user_ns - if not i.startswith('_') \ - and (user_ns[i] is not user_ns_hidden.get(i, nonmatching)) ] - - typelist = parameter_s.split() - if typelist: - typeset = set(typelist) - out = [i for i in out if type(user_ns[i]).__name__ in typeset] - - out.sort() - return out - - @skip_doctest - @line_magic - def who(self, parameter_s=''): - """Print all interactive variables, with some minimal formatting. - - If any arguments are given, only variables whose type matches one of - these are printed. For example:: - - %who function str - - will only list functions and strings, excluding all other types of - variables. To find the proper type names, simply use type(var) at a - command line to see how python prints type names. For example: - - :: - - In [1]: type('hello')\\ - Out[1]: <type 'str'> - - indicates that the type name for strings is 'str'. - - ``%who`` always excludes executed names loaded through your configuration - file and things which are internal to IPython. - - This is deliberate, as typically you may load many modules and the - purpose of %who is to show you only what you've manually defined. - - Examples - -------- - - Define two variables and list them with who:: - - In [1]: alpha = 123 - - In [2]: beta = 'test' - - In [3]: %who - alpha beta - - In [4]: %who int - alpha - - In [5]: %who str - beta - """ - - varlist = self.who_ls(parameter_s) - if not varlist: - if parameter_s: - print('No variables match your requested type.') - else: - print('Interactive namespace is empty.') - return - - # if we have variables, move on... - count = 0 - for i in varlist: - print(i+'\t', end=' ') - count += 1 - if count > 8: - count = 0 - print() - print() - - @skip_doctest - @line_magic - def whos(self, parameter_s=''): - """Like %who, but gives some extra information about each variable. - - The same type filtering of %who can be applied here. - - For all variables, the type is printed. Additionally it prints: - - - For {},[],(): their length. - - - For numpy arrays, a summary with shape, number of - elements, typecode and size in memory. - - - Everything else: a string representation, snipping their middle if - too long. - - Examples - -------- - Define two variables and list them with whos:: - - In [1]: alpha = 123 - - In [2]: beta = 'test' - - In [3]: %whos - Variable Type Data/Info - -------------------------------- - alpha int 123 - beta str test - """ - - varnames = self.who_ls(parameter_s) - if not varnames: - if parameter_s: - print('No variables match your requested type.') - else: - print('Interactive namespace is empty.') - return - - # if we have variables, move on... - - # for these types, show len() instead of data: - seq_types = ['dict', 'list', 'tuple'] - - # for numpy arrays, display summary info - ndarray_type = None - if 'numpy' in sys.modules: - try: - from numpy import ndarray - except ImportError: - pass - else: - ndarray_type = ndarray.__name__ - - # Find all variable names and types so we can figure out column sizes - - # some types are well known and can be shorter - abbrevs = {'IPython.core.macro.Macro' : 'Macro'} - def type_name(v): - tn = type(v).__name__ - return abbrevs.get(tn,tn) - - varlist = [self.shell.user_ns[n] for n in varnames] - - typelist = [] - for vv in varlist: - tt = type_name(vv) - - if tt=='instance': - typelist.append( abbrevs.get(str(vv.__class__), - str(vv.__class__))) - else: - typelist.append(tt) - - # column labels and # of spaces as separator - varlabel = 'Variable' - typelabel = 'Type' - datalabel = 'Data/Info' - colsep = 3 - # variable format strings - vformat = "{0:<{varwidth}}{1:<{typewidth}}" - aformat = "%s: %s elems, type `%s`, %s bytes" - # find the size of the columns to format the output nicely - varwidth = max(max(map(len,varnames)), len(varlabel)) + colsep - typewidth = max(max(map(len,typelist)), len(typelabel)) + colsep - # table header - print(varlabel.ljust(varwidth) + typelabel.ljust(typewidth) + \ - ' '+datalabel+'\n' + '-'*(varwidth+typewidth+len(datalabel)+1)) - # and the table itself - kb = 1024 - Mb = 1048576 # kb**2 - for vname,var,vtype in zip(varnames,varlist,typelist): - print(vformat.format(vname, vtype, varwidth=varwidth, typewidth=typewidth), end=' ') - if vtype in seq_types: - print("n="+str(len(var))) - elif vtype == ndarray_type: - vshape = str(var.shape).replace(',','').replace(' ','x')[1:-1] - if vtype==ndarray_type: - # numpy - vsize = var.size - vbytes = vsize*var.itemsize - vdtype = var.dtype - - if vbytes < 100000: - print(aformat % (vshape, vsize, vdtype, vbytes)) - else: - print(aformat % (vshape, vsize, vdtype, vbytes), end=' ') - if vbytes < Mb: - print('(%s kb)' % (vbytes/kb,)) - else: - print('(%s Mb)' % (vbytes/Mb,)) - else: - try: - vstr = str(var) - except UnicodeEncodeError: - vstr = var.encode(DEFAULT_ENCODING, - 'backslashreplace') - except: - vstr = "<object with id %d (str() failed)>" % id(var) - vstr = vstr.replace('\n', '\\n') - if len(vstr) < 50: - print(vstr) - else: - print(vstr[:25] + "<...>" + vstr[-25:]) - - @line_magic - def reset(self, parameter_s=''): - """Resets the namespace by removing all names defined by the user, if - called without arguments, or by removing some types of objects, such - as everything currently in IPython's In[] and Out[] containers (see - the parameters for details). - - Parameters - ---------- - -f - force reset without asking for confirmation. - -s - 'Soft' reset: Only clears your namespace, leaving history intact. - References to objects may be kept. By default (without this option), - we do a 'hard' reset, giving you a new session and removing all - references to objects from the current session. - --aggressive - Try to aggressively remove modules from sys.modules ; this - may allow you to reimport Python modules that have been updated and - pick up changes, but can have unattended consequences. - - in - reset input history - out - reset output history - dhist - reset directory history - array - reset only variables that are NumPy arrays - - See Also - -------- - reset_selective : invoked as ``%reset_selective`` - - Examples - -------- - :: - - In [6]: a = 1 - - In [7]: a - Out[7]: 1 - - In [8]: 'a' in get_ipython().user_ns - Out[8]: True - - In [9]: %reset -f - - In [1]: 'a' in get_ipython().user_ns - Out[1]: False - - In [2]: %reset -f in - Flushing input history - - In [3]: %reset -f dhist in - Flushing directory history - Flushing input history - - Notes - ----- - Calling this magic from clients that do not implement standard input, - such as the ipython notebook interface, will reset the namespace - without confirmation. - """ - opts, args = self.parse_options(parameter_s, "sf", "aggressive", mode="list") - if "f" in opts: - ans = True - else: - try: - ans = self.shell.ask_yes_no( - "Once deleted, variables cannot be recovered. Proceed (y/[n])?", - default='n') - except StdinNotImplementedError: - ans = True - if not ans: - print('Nothing done.') - return - - if 's' in opts: # Soft reset - user_ns = self.shell.user_ns - for i in self.who_ls(): - del(user_ns[i]) - elif len(args) == 0: # Hard reset - self.shell.reset(new_session=False, aggressive=("aggressive" in opts)) - - # reset in/out/dhist/array: previously extensinions/clearcmd.py - ip = self.shell - user_ns = self.shell.user_ns # local lookup, heavily used - - for target in args: - target = target.lower() # make matches case insensitive - if target == 'out': - print("Flushing output cache (%d entries)" % len(user_ns['_oh'])) - self.shell.displayhook.flush() - - elif target == 'in': - print("Flushing input history") - pc = self.shell.displayhook.prompt_count + 1 - for n in range(1, pc): - key = '_i'+repr(n) - user_ns.pop(key,None) - user_ns.update(dict(_i=u'',_ii=u'',_iii=u'')) - hm = ip.history_manager - # don't delete these, as %save and %macro depending on the - # length of these lists to be preserved - hm.input_hist_parsed[:] = [''] * pc - hm.input_hist_raw[:] = [''] * pc - # hm has internal machinery for _i,_ii,_iii, clear it out - hm._i = hm._ii = hm._iii = hm._i00 = u'' - - elif target == 'array': - # Support cleaning up numpy arrays - try: - from numpy import ndarray - # This must be done with items and not iteritems because - # we're going to modify the dict in-place. - for x,val in list(user_ns.items()): - if isinstance(val,ndarray): - del user_ns[x] - except ImportError: - print("reset array only works if Numpy is available.") - - elif target == 'dhist': - print("Flushing directory history") - del user_ns['_dh'][:] - - else: - print("Don't know how to reset ", end=' ') - print(target + ", please run `%reset?` for details") - - gc.collect() - - @line_magic - def reset_selective(self, parameter_s=''): - """Resets the namespace by removing names defined by the user. - - Input/Output history are left around in case you need them. - - %reset_selective [-f] regex - - No action is taken if regex is not included - - Options - -f : force reset without asking for confirmation. - - See Also - -------- - reset : invoked as ``%reset`` - - Examples - -------- - We first fully reset the namespace so your output looks identical to - this example for pedagogical reasons; in practice you do not need a - full reset:: - - In [1]: %reset -f - - Now, with a clean namespace we can make a few variables and use - ``%reset_selective`` to only delete names that match our regexp:: - - In [2]: a=1; b=2; c=3; b1m=4; b2m=5; b3m=6; b4m=7; b2s=8 - - In [3]: who_ls - Out[3]: ['a', 'b', 'b1m', 'b2m', 'b2s', 'b3m', 'b4m', 'c'] - - In [4]: %reset_selective -f b[2-3]m - - In [5]: who_ls - Out[5]: ['a', 'b', 'b1m', 'b2s', 'b4m', 'c'] - - In [6]: %reset_selective -f d - - In [7]: who_ls - Out[7]: ['a', 'b', 'b1m', 'b2s', 'b4m', 'c'] - - In [8]: %reset_selective -f c - - In [9]: who_ls - Out[9]: ['a', 'b', 'b1m', 'b2s', 'b4m'] - - In [10]: %reset_selective -f b - - In [11]: who_ls - Out[11]: ['a'] - - Notes - ----- - Calling this magic from clients that do not implement standard input, - such as the ipython notebook interface, will reset the namespace - without confirmation. - """ - - opts, regex = self.parse_options(parameter_s,'f') - - if 'f' in opts: - ans = True - else: - try: - ans = self.shell.ask_yes_no( - "Once deleted, variables cannot be recovered. Proceed (y/[n])? ", - default='n') - except StdinNotImplementedError: - ans = True - if not ans: - print('Nothing done.') - return - user_ns = self.shell.user_ns - if not regex: - print('No regex pattern specified. Nothing done.') - return - else: - try: - m = re.compile(regex) - except TypeError as e: - raise TypeError('regex must be a string or compiled pattern') from e - for i in self.who_ls(): - if m.search(i): - del(user_ns[i]) - - @line_magic - def xdel(self, parameter_s=''): - """Delete a variable, trying to clear it from anywhere that - IPython's machinery has references to it. By default, this uses - the identity of the named object in the user namespace to remove - references held under other names. The object is also removed - from the output history. - - Options - -n : Delete the specified name from all namespaces, without - checking their identity. - """ - opts, varname = self.parse_options(parameter_s,'n') - try: - self.shell.del_var(varname, ('n' in opts)) - except (NameError, ValueError) as e: - print(type(e).__name__ +": "+ str(e)) diff --git a/contrib/python/ipython/py3/IPython/core/magics/osm.py b/contrib/python/ipython/py3/IPython/core/magics/osm.py deleted file mode 100644 index 41957a2850..0000000000 --- a/contrib/python/ipython/py3/IPython/core/magics/osm.py +++ /dev/null @@ -1,854 +0,0 @@ -"""Implementation of magic functions for interaction with the OS. - -Note: this module is named 'osm' instead of 'os' to avoid a collision with the -builtin. -""" -# Copyright (c) IPython Development Team. -# Distributed under the terms of the Modified BSD License. - -import io -import os -import re -import sys -from pprint import pformat - -from IPython.core import magic_arguments -from IPython.core import oinspect -from IPython.core import page -from IPython.core.alias import AliasError, Alias -from IPython.core.error import UsageError -from IPython.core.magic import ( - Magics, compress_dhist, magics_class, line_magic, cell_magic, line_cell_magic -) -from IPython.testing.skipdoctest import skip_doctest -from IPython.utils.openpy import source_to_unicode -from IPython.utils.process import abbrev_cwd -from IPython.utils.terminal import set_term_title -from traitlets import Bool -from warnings import warn - - -@magics_class -class OSMagics(Magics): - """Magics to interact with the underlying OS (shell-type functionality). - """ - - cd_force_quiet = Bool(False, - help="Force %cd magic to be quiet even if -q is not passed." - ).tag(config=True) - - def __init__(self, shell=None, **kwargs): - - # Now define isexec in a cross platform manner. - self.is_posix = False - self.execre = None - if os.name == 'posix': - self.is_posix = True - else: - try: - winext = os.environ['pathext'].replace(';','|').replace('.','') - except KeyError: - winext = 'exe|com|bat|py' - try: - self.execre = re.compile(r'(.*)\.(%s)$' % winext,re.IGNORECASE) - except re.error: - warn("Seems like your pathext environmental " - "variable is malformed. Please check it to " - "enable a proper handle of file extensions " - "managed for your system") - winext = 'exe|com|bat|py' - self.execre = re.compile(r'(.*)\.(%s)$' % winext,re.IGNORECASE) - - # call up the chain - super().__init__(shell=shell, **kwargs) - - - def _isexec_POSIX(self, file): - """ - Test for executable on a POSIX system - """ - if os.access(file.path, os.X_OK): - # will fail on maxOS if access is not X_OK - return file.is_file() - return False - - - - def _isexec_WIN(self, file): - """ - Test for executable file on non POSIX system - """ - return file.is_file() and self.execre.match(file.name) is not None - - def isexec(self, file): - """ - Test for executable file on non POSIX system - """ - if self.is_posix: - return self._isexec_POSIX(file) - else: - return self._isexec_WIN(file) - - - @skip_doctest - @line_magic - def alias(self, parameter_s=''): - """Define an alias for a system command. - - '%alias alias_name cmd' defines 'alias_name' as an alias for 'cmd' - - Then, typing 'alias_name params' will execute the system command 'cmd - params' (from your underlying operating system). - - Aliases have lower precedence than magic functions and Python normal - variables, so if 'foo' is both a Python variable and an alias, the - alias can not be executed until 'del foo' removes the Python variable. - - You can use the %l specifier in an alias definition to represent the - whole line when the alias is called. For example:: - - In [2]: alias bracket echo "Input in brackets: <%l>" - In [3]: bracket hello world - Input in brackets: <hello world> - - You can also define aliases with parameters using %s specifiers (one - per parameter):: - - In [1]: alias parts echo first %s second %s - In [2]: %parts A B - first A second B - In [3]: %parts A - Incorrect number of arguments: 2 expected. - parts is an alias to: 'echo first %s second %s' - - Note that %l and %s are mutually exclusive. You can only use one or - the other in your aliases. - - Aliases expand Python variables just like system calls using ! or !! - do: all expressions prefixed with '$' get expanded. For details of - the semantic rules, see PEP-215: - https://peps.python.org/pep-0215/. This is the library used by - IPython for variable expansion. If you want to access a true shell - variable, an extra $ is necessary to prevent its expansion by - IPython:: - - In [6]: alias show echo - In [7]: PATH='A Python string' - In [8]: show $PATH - A Python string - In [9]: show $$PATH - /usr/local/lf9560/bin:/usr/local/intel/compiler70/ia32/bin:... - - You can use the alias facility to access all of $PATH. See the %rehashx - function, which automatically creates aliases for the contents of your - $PATH. - - If called with no parameters, %alias prints the current alias table - for your system. For posix systems, the default aliases are 'cat', - 'cp', 'mv', 'rm', 'rmdir', and 'mkdir', and other platform-specific - aliases are added. For windows-based systems, the default aliases are - 'copy', 'ddir', 'echo', 'ls', 'ldir', 'mkdir', 'ren', and 'rmdir'. - - You can see the definition of alias by adding a question mark in the - end:: - - In [1]: cat? - Repr: <alias cat for 'cat'>""" - - par = parameter_s.strip() - if not par: - aliases = sorted(self.shell.alias_manager.aliases) - # stored = self.shell.db.get('stored_aliases', {} ) - # for k, v in stored: - # atab.append(k, v[0]) - - print("Total number of aliases:", len(aliases)) - sys.stdout.flush() - return aliases - - # Now try to define a new one - try: - alias,cmd = par.split(None, 1) - except TypeError: - print(oinspect.getdoc(self.alias)) - return - - try: - self.shell.alias_manager.define_alias(alias, cmd) - except AliasError as e: - print(e) - # end magic_alias - - @line_magic - def unalias(self, parameter_s=''): - """Remove an alias""" - - aname = parameter_s.strip() - try: - self.shell.alias_manager.undefine_alias(aname) - except ValueError as e: - print(e) - return - - stored = self.shell.db.get('stored_aliases', {} ) - if aname in stored: - print("Removing %stored alias",aname) - del stored[aname] - self.shell.db['stored_aliases'] = stored - - @line_magic - def rehashx(self, parameter_s=''): - """Update the alias table with all executable files in $PATH. - - rehashx explicitly checks that every entry in $PATH is a file - with execute access (os.X_OK). - - Under Windows, it checks executability as a match against a - '|'-separated string of extensions, stored in the IPython config - variable win_exec_ext. This defaults to 'exe|com|bat'. - - This function also resets the root module cache of module completer, - used on slow filesystems. - """ - from IPython.core.alias import InvalidAliasError - - # for the benefit of module completer in ipy_completers.py - del self.shell.db['rootmodules_cache'] - - path = [os.path.abspath(os.path.expanduser(p)) for p in - os.environ.get('PATH','').split(os.pathsep)] - - syscmdlist = [] - savedir = os.getcwd() - - # Now walk the paths looking for executables to alias. - try: - # write the whole loop for posix/Windows so we don't have an if in - # the innermost part - if self.is_posix: - for pdir in path: - try: - os.chdir(pdir) - except OSError: - continue - - # for python 3.6+ rewrite to: with os.scandir(pdir) as dirlist: - dirlist = os.scandir(path=pdir) - for ff in dirlist: - if self.isexec(ff): - fname = ff.name - try: - # Removes dots from the name since ipython - # will assume names with dots to be python. - if not self.shell.alias_manager.is_alias(fname): - self.shell.alias_manager.define_alias( - fname.replace('.',''), fname) - except InvalidAliasError: - pass - else: - syscmdlist.append(fname) - else: - no_alias = Alias.blacklist - for pdir in path: - try: - os.chdir(pdir) - except OSError: - continue - - # for python 3.6+ rewrite to: with os.scandir(pdir) as dirlist: - dirlist = os.scandir(pdir) - for ff in dirlist: - fname = ff.name - base, ext = os.path.splitext(fname) - if self.isexec(ff) and base.lower() not in no_alias: - if ext.lower() == '.exe': - fname = base - try: - # Removes dots from the name since ipython - # will assume names with dots to be python. - self.shell.alias_manager.define_alias( - base.lower().replace('.',''), fname) - except InvalidAliasError: - pass - syscmdlist.append(fname) - - self.shell.db['syscmdlist'] = syscmdlist - finally: - os.chdir(savedir) - - @skip_doctest - @line_magic - def pwd(self, parameter_s=''): - """Return the current working directory path. - - Examples - -------- - :: - - In [9]: pwd - Out[9]: '/home/tsuser/sprint/ipython' - """ - try: - return os.getcwd() - except FileNotFoundError as e: - raise UsageError("CWD no longer exists - please use %cd to change directory.") from e - - @skip_doctest - @line_magic - def cd(self, parameter_s=''): - """Change the current working directory. - - This command automatically maintains an internal list of directories - you visit during your IPython session, in the variable ``_dh``. The - command :magic:`%dhist` shows this history nicely formatted. You can - also do ``cd -<tab>`` to see directory history conveniently. - Usage: - - - ``cd 'dir'``: changes to directory 'dir'. - - ``cd -``: changes to the last visited directory. - - ``cd -<n>``: changes to the n-th directory in the directory history. - - ``cd --foo``: change to directory that matches 'foo' in history - - ``cd -b <bookmark_name>``: jump to a bookmark set by %bookmark - - Hitting a tab key after ``cd -b`` allows you to tab-complete - bookmark names. - - .. note:: - ``cd <bookmark_name>`` is enough if there is no directory - ``<bookmark_name>``, but a bookmark with the name exists. - - Options: - - -q Be quiet. Do not print the working directory after the - cd command is executed. By default IPython's cd - command does print this directory, since the default - prompts do not display path information. - - .. note:: - Note that ``!cd`` doesn't work for this purpose because the shell - where ``!command`` runs is immediately discarded after executing - 'command'. - - Examples - -------- - :: - - In [10]: cd parent/child - /home/tsuser/parent/child - """ - - try: - oldcwd = os.getcwd() - except FileNotFoundError: - # Happens if the CWD has been deleted. - oldcwd = None - - numcd = re.match(r'(-)(\d+)$',parameter_s) - # jump in directory history by number - if numcd: - nn = int(numcd.group(2)) - try: - ps = self.shell.user_ns['_dh'][nn] - except IndexError: - print('The requested directory does not exist in history.') - return - else: - opts = {} - elif parameter_s.startswith('--'): - ps = None - fallback = None - pat = parameter_s[2:] - dh = self.shell.user_ns['_dh'] - # first search only by basename (last component) - for ent in reversed(dh): - if pat in os.path.basename(ent) and os.path.isdir(ent): - ps = ent - break - - if fallback is None and pat in ent and os.path.isdir(ent): - fallback = ent - - # if we have no last part match, pick the first full path match - if ps is None: - ps = fallback - - if ps is None: - print("No matching entry in directory history") - return - else: - opts = {} - - - else: - opts, ps = self.parse_options(parameter_s, 'qb', mode='string') - # jump to previous - if ps == '-': - try: - ps = self.shell.user_ns['_dh'][-2] - except IndexError as e: - raise UsageError('%cd -: No previous directory to change to.') from e - # jump to bookmark if needed - else: - if not os.path.isdir(ps) or 'b' in opts: - bkms = self.shell.db.get('bookmarks', {}) - - if ps in bkms: - target = bkms[ps] - print('(bookmark:%s) -> %s' % (ps, target)) - ps = target - else: - if 'b' in opts: - raise UsageError("Bookmark '%s' not found. " - "Use '%%bookmark -l' to see your bookmarks." % ps) - - # at this point ps should point to the target dir - if ps: - try: - os.chdir(os.path.expanduser(ps)) - if hasattr(self.shell, 'term_title') and self.shell.term_title: - set_term_title(self.shell.term_title_format.format(cwd=abbrev_cwd())) - except OSError: - print(sys.exc_info()[1]) - else: - cwd = os.getcwd() - dhist = self.shell.user_ns['_dh'] - if oldcwd != cwd: - dhist.append(cwd) - self.shell.db['dhist'] = compress_dhist(dhist)[-100:] - - else: - os.chdir(self.shell.home_dir) - if hasattr(self.shell, 'term_title') and self.shell.term_title: - set_term_title(self.shell.term_title_format.format(cwd="~")) - cwd = os.getcwd() - dhist = self.shell.user_ns['_dh'] - - if oldcwd != cwd: - dhist.append(cwd) - self.shell.db['dhist'] = compress_dhist(dhist)[-100:] - if not 'q' in opts and not self.cd_force_quiet and self.shell.user_ns['_dh']: - print(self.shell.user_ns['_dh'][-1]) - - @line_magic - def env(self, parameter_s=''): - """Get, set, or list environment variables. - - Usage:\\ - - :``%env``: lists all environment variables/values - :``%env var``: get value for var - :``%env var val``: set value for var - :``%env var=val``: set value for var - :``%env var=$val``: set value for var, using python expansion if possible - """ - if parameter_s.strip(): - split = '=' if '=' in parameter_s else ' ' - bits = parameter_s.split(split) - if len(bits) == 1: - key = parameter_s.strip() - if key in os.environ: - return os.environ[key] - else: - err = "Environment does not have key: {0}".format(key) - raise UsageError(err) - if len(bits) > 1: - return self.set_env(parameter_s) - env = dict(os.environ) - # hide likely secrets when printing the whole environment - for key in list(env): - if any(s in key.lower() for s in ('key', 'token', 'secret')): - env[key] = '<hidden>' - - return env - - @line_magic - def set_env(self, parameter_s): - """Set environment variables. Assumptions are that either "val" is a - name in the user namespace, or val is something that evaluates to a - string. - - Usage:\\ - %set_env var val: set value for var - %set_env var=val: set value for var - %set_env var=$val: set value for var, using python expansion if possible - """ - split = '=' if '=' in parameter_s else ' ' - bits = parameter_s.split(split, 1) - if not parameter_s.strip() or len(bits)<2: - raise UsageError("usage is 'set_env var=val'") - var = bits[0].strip() - val = bits[1].strip() - if re.match(r'.*\s.*', var): - # an environment variable with whitespace is almost certainly - # not what the user intended. what's more likely is the wrong - # split was chosen, ie for "set_env cmd_args A=B", we chose - # '=' for the split and should have chosen ' '. to get around - # this, users should just assign directly to os.environ or use - # standard magic {var} expansion. - err = "refusing to set env var with whitespace: '{0}'" - err = err.format(val) - raise UsageError(err) - os.environ[var] = val - print('env: {0}={1}'.format(var,val)) - - @line_magic - def pushd(self, parameter_s=''): - """Place the current dir on stack and change directory. - - Usage:\\ - %pushd ['dirname'] - """ - - dir_s = self.shell.dir_stack - tgt = os.path.expanduser(parameter_s) - cwd = os.getcwd().replace(self.shell.home_dir,'~') - if tgt: - self.cd(parameter_s) - dir_s.insert(0,cwd) - return self.shell.run_line_magic('dirs', '') - - @line_magic - def popd(self, parameter_s=''): - """Change to directory popped off the top of the stack. - """ - if not self.shell.dir_stack: - raise UsageError("%popd on empty stack") - top = self.shell.dir_stack.pop(0) - self.cd(top) - print("popd ->",top) - - @line_magic - def dirs(self, parameter_s=''): - """Return the current directory stack.""" - - return self.shell.dir_stack - - @line_magic - def dhist(self, parameter_s=''): - """Print your history of visited directories. - - %dhist -> print full history\\ - %dhist n -> print last n entries only\\ - %dhist n1 n2 -> print entries between n1 and n2 (n2 not included)\\ - - This history is automatically maintained by the %cd command, and - always available as the global list variable _dh. You can use %cd -<n> - to go to directory number <n>. - - Note that most of time, you should view directory history by entering - cd -<TAB>. - - """ - - dh = self.shell.user_ns['_dh'] - if parameter_s: - try: - args = map(int,parameter_s.split()) - except: - self.arg_err(self.dhist) - return - if len(args) == 1: - ini,fin = max(len(dh)-(args[0]),0),len(dh) - elif len(args) == 2: - ini,fin = args - fin = min(fin, len(dh)) - else: - self.arg_err(self.dhist) - return - else: - ini,fin = 0,len(dh) - print('Directory history (kept in _dh)') - for i in range(ini, fin): - print("%d: %s" % (i, dh[i])) - - @skip_doctest - @line_magic - def sc(self, parameter_s=''): - """Shell capture - run shell command and capture output (DEPRECATED use !). - - DEPRECATED. Suboptimal, retained for backwards compatibility. - - You should use the form 'var = !command' instead. Example: - - "%sc -l myfiles = ls ~" should now be written as - - "myfiles = !ls ~" - - myfiles.s, myfiles.l and myfiles.n still apply as documented - below. - - -- - %sc [options] varname=command - - IPython will run the given command using commands.getoutput(), and - will then update the user's interactive namespace with a variable - called varname, containing the value of the call. Your command can - contain shell wildcards, pipes, etc. - - The '=' sign in the syntax is mandatory, and the variable name you - supply must follow Python's standard conventions for valid names. - - (A special format without variable name exists for internal use) - - Options: - - -l: list output. Split the output on newlines into a list before - assigning it to the given variable. By default the output is stored - as a single string. - - -v: verbose. Print the contents of the variable. - - In most cases you should not need to split as a list, because the - returned value is a special type of string which can automatically - provide its contents either as a list (split on newlines) or as a - space-separated string. These are convenient, respectively, either - for sequential processing or to be passed to a shell command. - - For example:: - - # Capture into variable a - In [1]: sc a=ls *py - - # a is a string with embedded newlines - In [2]: a - Out[2]: 'setup.py\\nwin32_manual_post_install.py' - - # which can be seen as a list: - In [3]: a.l - Out[3]: ['setup.py', 'win32_manual_post_install.py'] - - # or as a whitespace-separated string: - In [4]: a.s - Out[4]: 'setup.py win32_manual_post_install.py' - - # a.s is useful to pass as a single command line: - In [5]: !wc -l $a.s - 146 setup.py - 130 win32_manual_post_install.py - 276 total - - # while the list form is useful to loop over: - In [6]: for f in a.l: - ...: !wc -l $f - ...: - 146 setup.py - 130 win32_manual_post_install.py - - Similarly, the lists returned by the -l option are also special, in - the sense that you can equally invoke the .s attribute on them to - automatically get a whitespace-separated string from their contents:: - - In [7]: sc -l b=ls *py - - In [8]: b - Out[8]: ['setup.py', 'win32_manual_post_install.py'] - - In [9]: b.s - Out[9]: 'setup.py win32_manual_post_install.py' - - In summary, both the lists and strings used for output capture have - the following special attributes:: - - .l (or .list) : value as list. - .n (or .nlstr): value as newline-separated string. - .s (or .spstr): value as space-separated string. - """ - - opts,args = self.parse_options(parameter_s, 'lv') - # Try to get a variable name and command to run - try: - # the variable name must be obtained from the parse_options - # output, which uses shlex.split to strip options out. - var,_ = args.split('=', 1) - var = var.strip() - # But the command has to be extracted from the original input - # parameter_s, not on what parse_options returns, to avoid the - # quote stripping which shlex.split performs on it. - _,cmd = parameter_s.split('=', 1) - except ValueError: - var,cmd = '','' - # If all looks ok, proceed - split = 'l' in opts - out = self.shell.getoutput(cmd, split=split) - if 'v' in opts: - print('%s ==\n%s' % (var, pformat(out))) - if var: - self.shell.user_ns.update({var:out}) - else: - return out - - @line_cell_magic - def sx(self, line='', cell=None): - """Shell execute - run shell command and capture output (!! is short-hand). - - %sx command - - IPython will run the given command using commands.getoutput(), and - return the result formatted as a list (split on '\\n'). Since the - output is _returned_, it will be stored in ipython's regular output - cache Out[N] and in the '_N' automatic variables. - - Notes: - - 1) If an input line begins with '!!', then %sx is automatically - invoked. That is, while:: - - !ls - - causes ipython to simply issue system('ls'), typing:: - - !!ls - - is a shorthand equivalent to:: - - %sx ls - - 2) %sx differs from %sc in that %sx automatically splits into a list, - like '%sc -l'. The reason for this is to make it as easy as possible - to process line-oriented shell output via further python commands. - %sc is meant to provide much finer control, but requires more - typing. - - 3) Just like %sc -l, this is a list with special attributes: - :: - - .l (or .list) : value as list. - .n (or .nlstr): value as newline-separated string. - .s (or .spstr): value as whitespace-separated string. - - This is very useful when trying to use such lists as arguments to - system commands.""" - - if cell is None: - # line magic - return self.shell.getoutput(line) - else: - opts,args = self.parse_options(line, '', 'out=') - output = self.shell.getoutput(cell) - out_name = opts.get('out', opts.get('o')) - if out_name: - self.shell.user_ns[out_name] = output - else: - return output - - system = line_cell_magic('system')(sx) - bang = cell_magic('!')(sx) - - @line_magic - def bookmark(self, parameter_s=''): - """Manage IPython's bookmark system. - - %bookmark <name> - set bookmark to current dir - %bookmark <name> <dir> - set bookmark to <dir> - %bookmark -l - list all bookmarks - %bookmark -d <name> - remove bookmark - %bookmark -r - remove all bookmarks - - You can later on access a bookmarked folder with:: - - %cd -b <name> - - or simply '%cd <name>' if there is no directory called <name> AND - there is such a bookmark defined. - - Your bookmarks persist through IPython sessions, but they are - associated with each profile.""" - - opts,args = self.parse_options(parameter_s,'drl',mode='list') - if len(args) > 2: - raise UsageError("%bookmark: too many arguments") - - bkms = self.shell.db.get('bookmarks',{}) - - if 'd' in opts: - try: - todel = args[0] - except IndexError as e: - raise UsageError( - "%bookmark -d: must provide a bookmark to delete") from e - else: - try: - del bkms[todel] - except KeyError as e: - raise UsageError( - "%%bookmark -d: Can't delete bookmark '%s'" % todel) from e - - elif 'r' in opts: - bkms = {} - elif 'l' in opts: - bks = sorted(bkms) - if bks: - size = max(map(len, bks)) - else: - size = 0 - fmt = '%-'+str(size)+'s -> %s' - print('Current bookmarks:') - for bk in bks: - print(fmt % (bk, bkms[bk])) - else: - if not args: - raise UsageError("%bookmark: You must specify the bookmark name") - elif len(args)==1: - bkms[args[0]] = os.getcwd() - elif len(args)==2: - bkms[args[0]] = args[1] - self.shell.db['bookmarks'] = bkms - - @line_magic - def pycat(self, parameter_s=''): - """Show a syntax-highlighted file through a pager. - - This magic is similar to the cat utility, but it will assume the file - to be Python source and will show it with syntax highlighting. - - This magic command can either take a local filename, an url, - an history range (see %history) or a macro as argument. - - If no parameter is given, prints out history of current session up to - this point. :: - - %pycat myscript.py - %pycat 7-27 - %pycat myMacro - %pycat http://www.example.com/myscript.py - """ - try: - cont = self.shell.find_user_code(parameter_s, skip_encoding_cookie=False) - except (ValueError, IOError): - print("Error: no such file, variable, URL, history range or macro") - return - - page.page(self.shell.pycolorize(source_to_unicode(cont))) - - @magic_arguments.magic_arguments() - @magic_arguments.argument( - '-a', '--append', action='store_true', default=False, - help='Append contents of the cell to an existing file. ' - 'The file will be created if it does not exist.' - ) - @magic_arguments.argument( - 'filename', type=str, - help='file to write' - ) - @cell_magic - def writefile(self, line, cell): - """Write the contents of the cell to a file. - - The file will be overwritten unless the -a (--append) flag is specified. - """ - args = magic_arguments.parse_argstring(self.writefile, line) - if re.match(r'^(\'.*\')|(".*")$', args.filename): - filename = os.path.expanduser(args.filename[1:-1]) - else: - filename = os.path.expanduser(args.filename) - - if os.path.exists(filename): - if args.append: - print("Appending to %s" % filename) - else: - print("Overwriting %s" % filename) - else: - print("Writing %s" % filename) - - mode = 'a' if args.append else 'w' - with io.open(filename, mode, encoding='utf-8') as f: - f.write(cell) diff --git a/contrib/python/ipython/py3/IPython/core/magics/packaging.py b/contrib/python/ipython/py3/IPython/core/magics/packaging.py deleted file mode 100644 index 2f7652c169..0000000000 --- a/contrib/python/ipython/py3/IPython/core/magics/packaging.py +++ /dev/null @@ -1,112 +0,0 @@ -"""Implementation of packaging-related magic functions. -""" -#----------------------------------------------------------------------------- -# Copyright (c) 2018 The IPython Development Team. -# -# Distributed under the terms of the Modified BSD License. -# -# The full license is in the file COPYING.txt, distributed with this software. -#----------------------------------------------------------------------------- - -import re -import shlex -import sys -from pathlib import Path - -from IPython.core.magic import Magics, magics_class, line_magic - - -def _is_conda_environment(): - """Return True if the current Python executable is in a conda env""" - # TODO: does this need to change on windows? - return Path(sys.prefix, "conda-meta", "history").exists() - - -def _get_conda_executable(): - """Find the path to the conda executable""" - # Check if there is a conda executable in the same directory as the Python executable. - # This is the case within conda's root environment. - conda = Path(sys.executable).parent / "conda" - if conda.is_file(): - return str(conda) - - # Otherwise, attempt to extract the executable from conda history. - # This applies in any conda environment. - history = Path(sys.prefix, "conda-meta", "history").read_text(encoding="utf-8") - match = re.search( - r"^#\s*cmd:\s*(?P<command>.*conda)\s[create|install]", - history, - flags=re.MULTILINE, - ) - if match: - return match.groupdict()["command"] - - # Fallback: assume conda is available on the system path. - return "conda" - - -CONDA_COMMANDS_REQUIRING_PREFIX = { - 'install', 'list', 'remove', 'uninstall', 'update', 'upgrade', -} -CONDA_COMMANDS_REQUIRING_YES = { - 'install', 'remove', 'uninstall', 'update', 'upgrade', -} -CONDA_ENV_FLAGS = {'-p', '--prefix', '-n', '--name'} -CONDA_YES_FLAGS = {'-y', '--y'} - - -@magics_class -class PackagingMagics(Magics): - """Magics related to packaging & installation""" - - @line_magic - def pip(self, line): - """Run the pip package manager within the current kernel. - - Usage: - %pip install [pkgs] - """ - python = sys.executable - if sys.platform == "win32": - python = '"' + python + '"' - else: - python = shlex.quote(python) - - self.shell.system(" ".join([python, "-m", "pip", line])) - - print("Note: you may need to restart the kernel to use updated packages.") - - @line_magic - def conda(self, line): - """Run the conda package manager within the current kernel. - - Usage: - %conda install [pkgs] - """ - if not _is_conda_environment(): - raise ValueError("The python kernel does not appear to be a conda environment. " - "Please use ``%pip install`` instead.") - - conda = _get_conda_executable() - args = shlex.split(line) - command = args[0] if len(args) > 0 else "" - args = args[1:] if len(args) > 1 else [""] - - extra_args = [] - - # When the subprocess does not allow us to respond "yes" during the installation, - # we need to insert --yes in the argument list for some commands - stdin_disabled = getattr(self.shell, 'kernel', None) is not None - needs_yes = command in CONDA_COMMANDS_REQUIRING_YES - has_yes = set(args).intersection(CONDA_YES_FLAGS) - if stdin_disabled and needs_yes and not has_yes: - extra_args.append("--yes") - - # Add --prefix to point conda installation to the current environment - needs_prefix = command in CONDA_COMMANDS_REQUIRING_PREFIX - has_prefix = set(args).intersection(CONDA_ENV_FLAGS) - if needs_prefix and not has_prefix: - extra_args.extend(["--prefix", sys.prefix]) - - self.shell.system(' '.join([conda, command] + extra_args + args)) - print("\nNote: you may need to restart the kernel to use updated packages.") diff --git a/contrib/python/ipython/py3/IPython/core/magics/pylab.py b/contrib/python/ipython/py3/IPython/core/magics/pylab.py deleted file mode 100644 index 0f3fff62fa..0000000000 --- a/contrib/python/ipython/py3/IPython/core/magics/pylab.py +++ /dev/null @@ -1,169 +0,0 @@ -"""Implementation of magic functions for matplotlib/pylab support. -""" -#----------------------------------------------------------------------------- -# Copyright (c) 2012 The IPython Development Team. -# -# Distributed under the terms of the Modified BSD License. -# -# The full license is in the file COPYING.txt, distributed with this software. -#----------------------------------------------------------------------------- - -#----------------------------------------------------------------------------- -# Imports -#----------------------------------------------------------------------------- - -# Our own packages -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 IPython.core.pylabtools import backends - -#----------------------------------------------------------------------------- -# Magic implementation classes -#----------------------------------------------------------------------------- - -magic_gui_arg = magic_arguments.argument( - 'gui', nargs='?', - help="""Name of the matplotlib backend to use %s. - If given, the corresponding matplotlib backend is used, - otherwise it will be matplotlib's default - (which you can set in your matplotlib config file). - """ % str(tuple(sorted(backends.keys()))) -) - - -@magics_class -class PylabMagics(Magics): - """Magics related to matplotlib's pylab support""" - - @skip_doctest - @line_magic - @magic_arguments.magic_arguments() - @magic_arguments.argument('-l', '--list', action='store_true', - help='Show available matplotlib backends') - @magic_gui_arg - def matplotlib(self, line=''): - """Set up matplotlib to work interactively. - - This function lets you activate matplotlib interactive support - at any point during an IPython session. It does not import anything - into the interactive namespace. - - If you are using the inline matplotlib backend in the IPython Notebook - you can set which figure formats are enabled using the following:: - - In [1]: from IPython.display import set_matplotlib_formats - - In [2]: set_matplotlib_formats('pdf', 'svg') - - The default for inline figures sets `bbox_inches` to 'tight'. This can - cause discrepancies between the displayed image and the identical - image created using `savefig`. This behavior can be disabled using the - `%config` magic:: - - In [3]: %config InlineBackend.print_figure_kwargs = {'bbox_inches':None} - - In addition, see the docstring of - `IPython.display.set_matplotlib_formats` and - `IPython.display.set_matplotlib_close` for more information on - changing additional behaviors of the inline backend. - - Examples - -------- - To enable the inline backend for usage with the IPython Notebook:: - - In [1]: %matplotlib inline - - In this case, where the matplotlib default is TkAgg:: - - In [2]: %matplotlib - Using matplotlib backend: TkAgg - - But you can explicitly request a different GUI backend:: - - In [3]: %matplotlib qt - - You can list the available backends using the -l/--list option:: - - In [4]: %matplotlib --list - Available matplotlib backends: ['osx', 'qt4', 'qt5', 'gtk3', 'gtk4', 'notebook', 'wx', 'qt', 'nbagg', - 'gtk', 'tk', 'inline'] - """ - args = magic_arguments.parse_argstring(self.matplotlib, line) - if args.list: - backends_list = list(backends.keys()) - print("Available matplotlib backends: %s" % backends_list) - else: - gui, backend = self.shell.enable_matplotlib(args.gui.lower() if isinstance(args.gui, str) else args.gui) - self._show_matplotlib_backend(args.gui, backend) - - @skip_doctest - @line_magic - @magic_arguments.magic_arguments() - @magic_arguments.argument( - '--no-import-all', action='store_true', default=None, - help="""Prevent IPython from performing ``import *`` into the interactive namespace. - - You can govern the default behavior of this flag with the - InteractiveShellApp.pylab_import_all configurable. - """ - ) - @magic_gui_arg - def pylab(self, line=''): - """Load numpy and matplotlib to work interactively. - - This function lets you activate pylab (matplotlib, numpy and - interactive support) at any point during an IPython session. - - %pylab makes the following imports:: - - import numpy - import matplotlib - from matplotlib import pylab, mlab, pyplot - np = numpy - plt = pyplot - - from IPython.display import display - from IPython.core.pylabtools import figsize, getfigs - - from pylab import * - from numpy import * - - If you pass `--no-import-all`, the last two `*` imports will be excluded. - - See the %matplotlib magic for more details about activating matplotlib - without affecting the interactive namespace. - """ - args = magic_arguments.parse_argstring(self.pylab, line) - if args.no_import_all is None: - # get default from Application - if Application.initialized(): - app = Application.instance() - try: - import_all = app.pylab_import_all - except AttributeError: - import_all = True - else: - # nothing specified, no app - default True - import_all = True - else: - # invert no-import flag - import_all = not args.no_import_all - - gui, backend, clobbered = self.shell.enable_pylab(args.gui, import_all=import_all) - self._show_matplotlib_backend(args.gui, backend) - print( - "%pylab is deprecated, use %matplotlib inline and import the required libraries." - ) - print("Populating the interactive namespace from numpy and matplotlib") - if clobbered: - warn("pylab import has clobbered these variables: %s" % clobbered + - "\n`%matplotlib` prevents importing * from pylab and numpy" - ) - - def _show_matplotlib_backend(self, gui, backend): - """show matplotlib message backend message""" - if not gui or gui == 'auto': - print("Using matplotlib backend: %s" % backend) diff --git a/contrib/python/ipython/py3/IPython/core/magics/script.py b/contrib/python/ipython/py3/IPython/core/magics/script.py deleted file mode 100644 index 9fd2fc6c0d..0000000000 --- a/contrib/python/ipython/py3/IPython/core/magics/script.py +++ /dev/null @@ -1,362 +0,0 @@ -"""Magic functions for running cells in various scripts.""" - -# Copyright (c) IPython Development Team. -# Distributed under the terms of the Modified BSD License. - -import asyncio -import atexit -import errno -import os -import signal -import sys -import time -from subprocess import CalledProcessError -from threading import Thread - -from traitlets import Any, Dict, List, default - -from IPython.core import magic_arguments -from IPython.core.async_helpers import _AsyncIOProxy -from IPython.core.magic import Magics, cell_magic, line_magic, magics_class -from IPython.utils.process import arg_split - -#----------------------------------------------------------------------------- -# Magic implementation classes -#----------------------------------------------------------------------------- - -def script_args(f): - """single decorator for adding script args""" - args = [ - magic_arguments.argument( - '--out', type=str, - help="""The variable in which to store stdout from the script. - If the script is backgrounded, this will be the stdout *pipe*, - instead of the stderr text itself and will not be auto closed. - """ - ), - magic_arguments.argument( - '--err', type=str, - help="""The variable in which to store stderr from the script. - If the script is backgrounded, this will be the stderr *pipe*, - instead of the stderr text itself and will not be autoclosed. - """ - ), - magic_arguments.argument( - '--bg', action="store_true", - help="""Whether to run the script in the background. - If given, the only way to see the output of the command is - with --out/err. - """ - ), - magic_arguments.argument( - '--proc', type=str, - help="""The variable in which to store Popen instance. - This is used only when --bg option is given. - """ - ), - magic_arguments.argument( - '--no-raise-error', action="store_false", dest='raise_error', - help="""Whether you should raise an error message in addition to - a stream on stderr if you get a nonzero exit code. - """, - ), - ] - for arg in args: - f = arg(f) - return f - - -@magics_class -class ScriptMagics(Magics): - """Magics for talking to scripts - - This defines a base `%%script` cell magic for running a cell - with a program in a subprocess, and registers a few top-level - magics that call %%script with common interpreters. - """ - - event_loop = Any( - help=""" - The event loop on which to run subprocesses - - Not the main event loop, - because we want to be able to make blocking calls - and have certain requirements we don't want to impose on the main loop. - """ - ) - - script_magics = List( - help="""Extra script cell magics to define - - This generates simple wrappers of `%%script foo` as `%%foo`. - - If you want to add script magics that aren't on your path, - specify them in script_paths - """, - ).tag(config=True) - @default('script_magics') - def _script_magics_default(self): - """default to a common list of programs""" - - defaults = [ - 'sh', - 'bash', - 'perl', - 'ruby', - 'python', - 'python2', - 'python3', - 'pypy', - ] - if os.name == 'nt': - defaults.extend([ - 'cmd', - ]) - - return defaults - - 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) - - def __init__(self, shell=None): - super(ScriptMagics, self).__init__(shell=shell) - self._generate_script_magics() - self.bg_processes = [] - atexit.register(self.kill_bg_processes) - - def __del__(self): - self.kill_bg_processes() - - def _generate_script_magics(self): - cell_magics = self.magics['cell'] - for name in self.script_magics: - cell_magics[name] = self._make_script_magic(name) - - def _make_script_magic(self, name): - """make a named magic, that calls %%script with a particular program""" - # expand to explicit path if necessary: - script = self.script_paths.get(name, name) - - @magic_arguments.magic_arguments() - @script_args - def named_script_magic(line, cell): - # if line, add it as cl-flags - if line: - line = "%s %s" % (script, line) - else: - line = script - return self.shebang(line, cell) - - # write a basic docstring: - named_script_magic.__doc__ = \ - """%%{name} script magic - - Run cells with {script} in a subprocess. - - This is a shortcut for `%%script {script}` - """.format(**locals()) - - return named_script_magic - - @magic_arguments.magic_arguments() - @script_args - @cell_magic("script") - def shebang(self, line, cell): - """Run a cell via a shell command - - The `%%script` line is like the #! line of script, - specifying a program (bash, perl, ruby, etc.) with which to run. - - The rest of the cell is run by that program. - - Examples - -------- - :: - - In [1]: %%script bash - ...: for i in 1 2 3; do - ...: echo $i - ...: done - 1 - 2 - 3 - """ - - # Create the event loop in which to run script magics - # this operates on a background thread - if self.event_loop is None: - if sys.platform == "win32": - # don't override the current policy, - # just create an event loop - event_loop = asyncio.WindowsProactorEventLoopPolicy().new_event_loop() - else: - event_loop = asyncio.new_event_loop() - self.event_loop = event_loop - - # start the loop in a background thread - asyncio_thread = Thread(target=event_loop.run_forever, daemon=True) - asyncio_thread.start() - else: - event_loop = self.event_loop - - def in_thread(coro): - """Call a coroutine on the asyncio thread""" - return asyncio.run_coroutine_threadsafe(coro, event_loop).result() - - async def _handle_stream(stream, stream_arg, file_object): - while True: - line = (await stream.readline()).decode("utf8") - if not line: - break - if stream_arg: - self.shell.user_ns[stream_arg] = line - else: - file_object.write(line) - file_object.flush() - - async def _stream_communicate(process, cell): - process.stdin.write(cell) - process.stdin.close() - stdout_task = asyncio.create_task( - _handle_stream(process.stdout, args.out, sys.stdout) - ) - stderr_task = asyncio.create_task( - _handle_stream(process.stderr, args.err, sys.stderr) - ) - await asyncio.wait([stdout_task, stderr_task]) - await process.wait() - - argv = arg_split(line, posix=not sys.platform.startswith("win")) - args, cmd = self.shebang.parser.parse_known_args(argv) - - try: - p = in_thread( - asyncio.create_subprocess_exec( - *cmd, - stdout=asyncio.subprocess.PIPE, - stderr=asyncio.subprocess.PIPE, - stdin=asyncio.subprocess.PIPE, - ) - ) - except OSError as e: - if e.errno == errno.ENOENT: - print("Couldn't find program: %r" % cmd[0]) - return - else: - raise - - if not cell.endswith('\n'): - cell += '\n' - cell = cell.encode('utf8', 'replace') - if args.bg: - self.bg_processes.append(p) - self._gc_bg_processes() - to_close = [] - if args.out: - self.shell.user_ns[args.out] = _AsyncIOProxy(p.stdout, event_loop) - else: - to_close.append(p.stdout) - if args.err: - self.shell.user_ns[args.err] = _AsyncIOProxy(p.stderr, event_loop) - else: - to_close.append(p.stderr) - event_loop.call_soon_threadsafe( - lambda: asyncio.Task(self._run_script(p, cell, to_close)) - ) - if args.proc: - proc_proxy = _AsyncIOProxy(p, event_loop) - proc_proxy.stdout = _AsyncIOProxy(p.stdout, event_loop) - proc_proxy.stderr = _AsyncIOProxy(p.stderr, event_loop) - self.shell.user_ns[args.proc] = proc_proxy - return - - try: - in_thread(_stream_communicate(p, cell)) - except KeyboardInterrupt: - try: - p.send_signal(signal.SIGINT) - in_thread(asyncio.wait_for(p.wait(), timeout=0.1)) - if p.returncode is not None: - print("Process is interrupted.") - return - p.terminate() - in_thread(asyncio.wait_for(p.wait(), timeout=0.1)) - if p.returncode is not None: - print("Process is terminated.") - return - p.kill() - print("Process is killed.") - except OSError: - pass - except Exception as e: - print("Error while terminating subprocess (pid=%i): %s" % (p.pid, e)) - return - - if args.raise_error and p.returncode != 0: - # If we get here and p.returncode is still None, we must have - # killed it but not yet seen its return code. We don't wait for it, - # in case it's stuck in uninterruptible sleep. -9 = SIGKILL - rc = p.returncode or -9 - raise CalledProcessError(rc, cell) - - shebang.__skip_doctest__ = os.name != "posix" - - async def _run_script(self, p, cell, to_close): - """callback for running the script in the background""" - - p.stdin.write(cell) - await p.stdin.drain() - p.stdin.close() - await p.stdin.wait_closed() - await p.wait() - # asyncio read pipes have no close - # but we should drain the data anyway - for s in to_close: - await s.read() - self._gc_bg_processes() - - @line_magic("killbgscripts") - def killbgscripts(self, _nouse_=''): - """Kill all BG processes started by %%script and its family.""" - self.kill_bg_processes() - print("All background processes were killed.") - - def kill_bg_processes(self): - """Kill all BG processes which are still running.""" - if not self.bg_processes: - return - for p in self.bg_processes: - if p.returncode is None: - try: - p.send_signal(signal.SIGINT) - except: - pass - time.sleep(0.1) - self._gc_bg_processes() - if not self.bg_processes: - return - for p in self.bg_processes: - if p.returncode is None: - try: - p.terminate() - except: - pass - time.sleep(0.1) - self._gc_bg_processes() - if not self.bg_processes: - return - for p in self.bg_processes: - if p.returncode is None: - try: - p.kill() - except: - pass - self._gc_bg_processes() - - def _gc_bg_processes(self): - self.bg_processes = [p for p in self.bg_processes if p.returncode is None] diff --git a/contrib/python/ipython/py3/IPython/core/oinspect.py b/contrib/python/ipython/py3/IPython/core/oinspect.py deleted file mode 100644 index 1a5c0ae070..0000000000 --- a/contrib/python/ipython/py3/IPython/core/oinspect.py +++ /dev/null @@ -1,1055 +0,0 @@ -# -*- coding: utf-8 -*- -"""Tools for inspecting Python objects. - -Uses syntax highlighting for presenting the various information elements. - -Similar in spirit to the inspect module, but all calls take a name argument to -reference the name under which an object is being read. -""" - -# Copyright (c) IPython Development Team. -# Distributed under the terms of the Modified BSD License. - -__all__ = ['Inspector','InspectColors'] - -# stdlib modules -import ast -import inspect -from inspect import signature -import linecache -import warnings -import os -from textwrap import dedent -import types -import io as stdlib_io - -from typing import Union - -# IPython's own -from IPython.core import page -from IPython.lib.pretty import pretty -from IPython.testing.skipdoctest import skip_doctest -from IPython.utils import PyColorize -from IPython.utils import openpy -from IPython.utils import py3compat -from IPython.utils.dir2 import safe_hasattr -from IPython.utils.path import compress_user -from IPython.utils.text import indent -from IPython.utils.wildcard import list_namespace -from IPython.utils.wildcard import typestr2type -from IPython.utils.coloransi import TermColors, ColorScheme, ColorSchemeTable -from IPython.utils.py3compat import cast_unicode -from IPython.utils.colorable import Colorable -from IPython.utils.decorators import undoc - -from pygments import highlight -from pygments.lexers import PythonLexer -from pygments.formatters import HtmlFormatter - -def pylight(code): - return highlight(code, PythonLexer(), HtmlFormatter(noclasses=True)) - -# builtin docstrings to ignore -_func_call_docstring = types.FunctionType.__call__.__doc__ -_object_init_docstring = object.__init__.__doc__ -_builtin_type_docstrings = { - inspect.getdoc(t) for t in (types.ModuleType, types.MethodType, - types.FunctionType, property) -} - -_builtin_func_type = type(all) -_builtin_meth_type = type(str.upper) # Bound methods have the same type as builtin functions -#**************************************************************************** -# Builtin color schemes - -Colors = TermColors # just a shorthand - -InspectColors = PyColorize.ANSICodeColors - -#**************************************************************************** -# Auxiliary functions and objects - -# See the messaging spec for the definition of all these fields. This list -# effectively defines the order of display -info_fields = ['type_name', 'base_class', 'string_form', 'namespace', - 'length', 'file', 'definition', 'docstring', 'source', - 'init_definition', 'class_docstring', 'init_docstring', - 'call_def', 'call_docstring', - # These won't be printed but will be used to determine how to - # format the object - 'ismagic', 'isalias', 'isclass', 'found', 'name' - ] - - -def object_info(**kw): - """Make an object info dict with all fields present.""" - infodict = {k:None for k in info_fields} - infodict.update(kw) - return infodict - - -def get_encoding(obj): - """Get encoding for python source file defining obj - - Returns None if obj is not defined in a sourcefile. - """ - ofile = find_file(obj) - # run contents of file through pager starting at line where the object - # is defined, as long as the file isn't binary and is actually on the - # filesystem. - if ofile is None: - return None - elif ofile.endswith(('.so', '.dll', '.pyd')): - return None - elif not os.path.isfile(ofile): - return None - else: - # Print only text files, not extension binaries. Note that - # getsourcelines returns lineno with 1-offset and page() uses - # 0-offset, so we must adjust. - with stdlib_io.open(ofile, 'rb') as buffer: # Tweaked to use io.open for Python 2 - encoding, lines = openpy.detect_encoding(buffer.readline) - return encoding - -def getdoc(obj) -> Union[str,None]: - """Stable wrapper around inspect.getdoc. - - This can't crash because of attribute problems. - - 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. - """ - # Allow objects to offer customized documentation via a getdoc method: - try: - ds = obj.getdoc() - except Exception: - pass - else: - if isinstance(ds, str): - return inspect.cleandoc(ds) - docstr = inspect.getdoc(obj) - return docstr - - -def getsource(obj, oname='') -> Union[str,None]: - """Wrapper around inspect.getsource. - - This can be modified by other projects to provide customized source - extraction. - - Parameters - ---------- - obj : object - an object whose source code we will attempt to extract - oname : str - (optional) a name under which the object is known - - Returns - ------- - src : unicode or None - - """ - - if isinstance(obj, property): - sources = [] - for attrname in ['fget', 'fset', 'fdel']: - fn = getattr(obj, attrname) - if fn is not None: - encoding = get_encoding(fn) - oname_prefix = ('%s.' % oname) if oname else '' - sources.append(''.join(('# ', oname_prefix, attrname))) - if inspect.isfunction(fn): - sources.append(dedent(getsource(fn))) - else: - # Default str/repr only prints function name, - # pretty.pretty prints module name too. - sources.append( - '%s%s = %s\n' % (oname_prefix, attrname, pretty(fn)) - ) - if sources: - return '\n'.join(sources) - else: - return None - - else: - # Get source for non-property objects. - - obj = _get_wrapped(obj) - - try: - src = inspect.getsource(obj) - except TypeError: - # The object itself provided no meaningful source, try looking for - # its class definition instead. - try: - src = inspect.getsource(obj.__class__) - except (OSError, TypeError): - return None - except OSError: - return None - - return src - - -def is_simple_callable(obj): - """True if obj is a function ()""" - return (inspect.isfunction(obj) or inspect.ismethod(obj) or \ - isinstance(obj, _builtin_func_type) or isinstance(obj, _builtin_meth_type)) - -@undoc -def getargspec(obj): - """Wrapper around :func:`inspect.getfullargspec` - - In addition to functions and methods, this can also handle objects with a - ``__call__`` attribute. - - DEPRECATED: Deprecated since 7.10. Do not use, will be removed. - """ - - warnings.warn('`getargspec` function is deprecated as of IPython 7.10' - 'and will be removed in future versions.', DeprecationWarning, stacklevel=2) - - if safe_hasattr(obj, '__call__') and not is_simple_callable(obj): - obj = obj.__call__ - - return inspect.getfullargspec(obj) - -@undoc -def format_argspec(argspec): - """Format argspect, convenience wrapper around inspect's. - - This takes a dict instead of ordered arguments and calls - inspect.format_argspec with the arguments in the necessary order. - - DEPRECATED (since 7.10): Do not use; will be removed in future versions. - """ - - warnings.warn('`format_argspec` function is deprecated as of IPython 7.10' - 'and will be removed in future versions.', DeprecationWarning, stacklevel=2) - - - return inspect.formatargspec(argspec['args'], argspec['varargs'], - argspec['varkw'], argspec['defaults']) - -@undoc -def call_tip(oinfo, format_call=True): - """DEPRECATED since 6.0. Extract call tip data from an oinfo dict.""" - warnings.warn( - "`call_tip` function is deprecated as of IPython 6.0" - "and will be removed in future versions.", - DeprecationWarning, - stacklevel=2, - ) - # Get call definition - argspec = oinfo.get('argspec') - if argspec is None: - call_line = None - else: - # Callable objects will have 'self' as their first argument, prune - # it out if it's there for clarity (since users do *not* pass an - # extra first argument explicitly). - try: - has_self = argspec['args'][0] == 'self' - except (KeyError, IndexError): - pass - else: - if has_self: - argspec['args'] = argspec['args'][1:] - - call_line = oinfo['name']+format_argspec(argspec) - - # Now get docstring. - # The priority is: call docstring, constructor docstring, main one. - doc = oinfo.get('call_docstring') - if doc is None: - doc = oinfo.get('init_docstring') - if doc is None: - doc = oinfo.get('docstring','') - - return call_line, doc - - -def _get_wrapped(obj): - """Get the original object if wrapped in one or more @decorators - - Some objects automatically construct similar objects on any unrecognised - attribute access (e.g. unittest.mock.call). To protect against infinite loops, - this will arbitrarily cut off after 100 levels of obj.__wrapped__ - attribute access. --TK, Jan 2016 - """ - orig_obj = obj - i = 0 - while safe_hasattr(obj, '__wrapped__'): - obj = obj.__wrapped__ - i += 1 - if i > 100: - # __wrapped__ is probably a lie, so return the thing we started with - return orig_obj - return obj - -def find_file(obj) -> str: - """Find the absolute path to the file where an object was defined. - - This is essentially a robust wrapper around `inspect.getabsfile`. - - Returns None if no file can be found. - - Parameters - ---------- - obj : any Python object - - Returns - ------- - fname : str - The absolute path to the file where the object was defined. - """ - obj = _get_wrapped(obj) - - fname = None - try: - fname = inspect.getabsfile(obj) - except TypeError: - # For an instance, the file that matters is where its class was - # declared. - try: - fname = inspect.getabsfile(obj.__class__) - except (OSError, TypeError): - # Can happen for builtins - pass - except OSError: - pass - - return cast_unicode(fname) - - -def find_source_lines(obj): - """Find the line number in a file where an object was defined. - - This is essentially a robust wrapper around `inspect.getsourcelines`. - - Returns None if no file can be found. - - Parameters - ---------- - obj : any Python object - - Returns - ------- - lineno : int - The line number where the object definition starts. - """ - obj = _get_wrapped(obj) - - try: - lineno = inspect.getsourcelines(obj)[1] - except TypeError: - # For instances, try the class object like getsource() does - try: - lineno = inspect.getsourcelines(obj.__class__)[1] - except (OSError, TypeError): - return None - except OSError: - return None - - return lineno - -class Inspector(Colorable): - - def __init__(self, color_table=InspectColors, - code_color_table=PyColorize.ANSICodeColors, - scheme=None, - 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.format = self.parser.format - self.str_detail_level = str_detail_level - self.set_active_scheme(scheme) - - def _getdef(self,obj,oname='') -> Union[str,None]: - """Return the call signature for any callable object. - - If any exception is generated, None is returned instead and the - exception is suppressed.""" - try: - return _render_signature(signature(obj), oname) - except: - return None - - def __head(self,h) -> str: - """Return a header string with proper colors.""" - return '%s%s%s' % (self.color_table.active_colors.header,h, - self.color_table.active_colors.normal) - - def set_active_scheme(self, scheme): - if scheme is not None: - self.color_table.set_active_scheme(scheme) - self.parser.color_table.set_active_scheme(scheme) - - def noinfo(self, msg, oname): - """Generic message when no information is found.""" - print('No %s found' % msg, end=' ') - if oname: - print('for %s' % oname) - else: - print() - - def pdef(self, obj, oname=''): - """Print the call signature for any callable object. - - If the object is a class, print the constructor information.""" - - if not callable(obj): - print('Object is not callable.') - return - - header = '' - - if inspect.isclass(obj): - header = self.__head('Class constructor information:\n') - - - output = self._getdef(obj,oname) - if output is None: - self.noinfo('definition header',oname) - else: - print(header,self.format(output), end=' ') - - # In Python 3, all classes are new-style, so they all have __init__. - @skip_doctest - def pdoc(self, obj, oname='', formatter=None): - """Print the docstring for any object. - - Optional: - -formatter: a function to run the docstring through for specially - formatted docstrings. - - Examples - -------- - In [1]: class NoInit: - ...: pass - - In [2]: class NoDoc: - ...: def __init__(self): - ...: pass - - In [3]: %pdoc NoDoc - No documentation found for NoDoc - - In [4]: %pdoc NoInit - No documentation found for NoInit - - In [5]: obj = NoInit() - - In [6]: %pdoc obj - No documentation found for obj - - In [5]: obj2 = NoDoc() - - In [6]: %pdoc obj2 - No documentation found for obj2 - """ - - head = self.__head # For convenience - lines = [] - ds = getdoc(obj) - if formatter: - ds = formatter(ds).get('plain/text', ds) - if ds: - lines.append(head("Class docstring:")) - lines.append(indent(ds)) - if inspect.isclass(obj) and hasattr(obj, '__init__'): - init_ds = getdoc(obj.__init__) - if init_ds is not None: - lines.append(head("Init docstring:")) - lines.append(indent(init_ds)) - elif hasattr(obj,'__call__'): - call_ds = getdoc(obj.__call__) - if call_ds: - lines.append(head("Call docstring:")) - lines.append(indent(call_ds)) - - if not lines: - self.noinfo('documentation',oname) - else: - page.page('\n'.join(lines)) - - def psource(self, obj, oname=''): - """Print the source code for an object.""" - - # Flush the source cache because inspect can return out-of-date source - linecache.checkcache() - try: - src = getsource(obj, oname=oname) - except Exception: - src = None - - if src is None: - self.noinfo('source', oname) - else: - page.page(self.format(src)) - - 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) - return - - ofile = find_file(obj) - # run contents of file through pager starting at line where the object - # is defined, as long as the file isn't binary and is actually on the - # filesystem. - if ofile.endswith(('.so', '.dll', '.pyd')): - print('File %r is binary, not printing.' % ofile) - elif not os.path.isfile(ofile): - print('File %r does not exist, not printing.' % ofile) - else: - # Print only text files, not extension binaries. Note that - # getsourcelines returns lineno with 1-offset and page() uses - # 0-offset, so we must adjust. - page.page(self.format(openpy.read_py_file(ofile, skip_encoding_cookie=False)), lineno - 1) - - - def _mime_format(self, text:str, formatter=None) -> dict: - """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. - - """ - 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, omit_sections=() - ): - """Retrieve an info dict and format it. - - Parameters - ---------- - obj : any - Object to inspect and return info from - oname : str (default: ''): - Name of the variable pointing to `obj`. - formatter : callable - info - already computed information - detail_level : integer - Granularity of detail level, if set to 1, give more information. - omit_sections : container[str] - Titles or keys to omit from output (can be set, tuple, etc., anything supporting `in`) - """ - - info = self.info(obj, oname=oname, info=info, detail_level=detail_level) - - _mime = { - 'text/plain': [], - 'text/html': '', - } - - def append_field(bundle, title:str, key:str, formatter=None): - if title in omit_sections or key in omit_sections: - return - 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') - - elif info['ismagic']: - if detail_level > 0: - append_field(_mime, 'Source', 'source', code_formatter) - else: - 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, 'Docstring', 'docstring', formatter) - if detail_level > 0 and info['source']: - append_field(_mime, 'Source', 'source', code_formatter) - else: - append_field(_mime, 'Init docstring', 'init_docstring', formatter) - - append_field(_mime, 'File', 'file') - append_field(_mime, 'Type', 'type_name') - append_field(_mime, 'Subclasses', 'subclasses') - - 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, 'String form', 'string_form') - - # Namespace - if info['namespace'] != 'Interactive': - append_field(_mime, 'Namespace', 'namespace') - - 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 and info['source']: - 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, - omit_sections=(), - ): - """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 dictionary. - - 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. - - - omit_sections: set of section keys and titles to omit - """ - info = self._get_info( - obj, oname, formatter, info, detail_level, omit_sections=omit_sections - ) - if not enable_html_pager: - del info['text/html'] - page.page(info) - - def _info(self, obj, oname="", info=None, detail_level=0): - """ - Inspector.info() was likely improperly marked as deprecated - while only a parameter was deprecated. We "un-deprecate" it. - """ - - warnings.warn( - "The `Inspector.info()` method has been un-deprecated as of 8.0 " - "and the `formatter=` keyword removed. `Inspector._info` is now " - "an alias, and you can just call `.info()` directly.", - 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) -> dict: - """Compute a dict with detailed information about an object. - - Parameters - ---------- - obj : any - An object to find information about - oname : str (default: '') - Name of the variable pointing to `obj`. - info : (default: None) - A struct (dict like with attr access) with some information fields - which may have been precomputed already. - detail_level : int (default:0) - If set to 1, more information is given. - - Returns - ------- - An object info dict with known fields from `info_fields`. Keys are - strings, values are string or None. - """ - - if info is None: - ismagic = False - isalias = False - ospace = '' - else: - ismagic = info.ismagic - isalias = info.isalias - ospace = info.namespace - - # Get docstring, special-casing aliases: - if isalias: - if not callable(obj): - try: - ds = "Alias to the system command:\n %s" % obj[1] - except: - ds = "Alias: " + str(obj) - else: - ds = "Alias to " + str(obj) - if obj.__doc__: - ds += "\nDocstring:\n" + obj.__doc__ - else: - ds = getdoc(obj) - if ds is None: - ds = '<no docstring>' - - # store output in a dict, we initialize it here and fill it as we go - out = dict(name=oname, found=True, isalias=isalias, ismagic=ismagic, subclasses=None) - - string_max = 200 # max size of strings to show (snipped if longer) - shalf = int((string_max - 5) / 2) - - if ismagic: - out['type_name'] = 'Magic function' - elif isalias: - out['type_name'] = 'System alias' - else: - out['type_name'] = type(obj).__name__ - - try: - bclass = obj.__class__ - out['base_class'] = str(bclass) - except: - pass - - # String form, but snip if too long in ? form (full in ??) - if detail_level >= self.str_detail_level: - try: - ostr = str(obj) - str_head = 'string_form' - if not detail_level and len(ostr)>string_max: - ostr = ostr[:shalf] + ' <...> ' + ostr[-shalf:] - ostr = ("\n" + " " * len(str_head.expandtabs())).\ - join(q.strip() for q in ostr.split("\n")) - out[str_head] = ostr - except: - pass - - if ospace: - out['namespace'] = ospace - - # Length (for strings and lists) - try: - out['length'] = str(len(obj)) - except Exception: - pass - - # Filename where object was defined - binary_file = False - fname = find_file(obj) - if fname is None: - # if anything goes wrong, we don't want to show source, so it's as - # if the file was binary - binary_file = True - else: - if fname.endswith(('.so', '.dll', '.pyd')): - binary_file = True - elif fname.endswith('<string>'): - fname = 'Dynamically generated function. No source code available.' - out['file'] = compress_user(fname) - - # Original source code for a callable, class or property. - if detail_level: - # Flush the source cache because inspect can return out-of-date - # source - linecache.checkcache() - try: - if isinstance(obj, property) or not binary_file: - src = getsource(obj, oname) - if src is not None: - src = src.rstrip() - out['source'] = src - - except Exception: - pass - - # Add docstring only if no source is to be shown (avoid repetitions). - if ds and not self._source_contains_docstring(out.get('source'), ds): - out['docstring'] = ds - - # Constructor docstring for classes - if inspect.isclass(obj): - out['isclass'] = True - - # get the init signature: - try: - 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 - 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) - # 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 - - names = [sub.__name__ for sub in type.__subclasses__(obj)] - if len(names) < 10: - all_names = ', '.join(names) - else: - all_names = ', '.join(names[:10]+['...']) - out['subclasses'] = all_names - # and class docstring for instances: - else: - # reconstruct the function definition and print it: - defln = self._getdef(obj, oname) - if 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 - # most cases they will, but it's nice to print all the info for - # objects which use instance-customized docstrings. - if ds: - try: - cls = getattr(obj,'__class__') - except: - class_ds = None - else: - class_ds = getdoc(cls) - # Skip Python's auto-generated docstrings - if class_ds in _builtin_type_docstrings: - class_ds = None - if class_ds and ds != class_ds: - out['class_docstring'] = class_ds - - # Next, try to show constructor docstrings - try: - init_ds = getdoc(obj.__init__) - # Skip Python's auto-generated docstrings - if init_ds == _object_init_docstring: - init_ds = None - except AttributeError: - init_ds = None - if init_ds: - out['init_docstring'] = init_ds - - # 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')): - # 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 - call_ds = getdoc(obj.__call__) - # Skip Python's auto-generated docstrings - if call_ds == _func_call_docstring: - call_ds = None - if call_ds: - out['call_docstring'] = call_ds - - return object_info(**out) - - @staticmethod - def _source_contains_docstring(src, doc): - """ - Check whether the source *src* contains the docstring *doc*. - - This is is helper function to skip displaying the docstring if the - source already contains it, avoiding repetition of information. - """ - try: - def_node, = ast.parse(dedent(src)).body - return ast.get_docstring(def_node) == doc - except Exception: - # The source can become invalid or even non-existent (because it - # is re-fetched from the source file) so the above code fail in - # arbitrary ways. - return False - - def psearch(self,pattern,ns_table,ns_search=[], - ignore_case=False,show_all=False, *, list_types=False): - """Search namespaces with wildcards for objects. - - Arguments: - - - pattern: string containing shell-like wildcards to use in namespace - searches and optionally a type specification to narrow the search to - objects of that type. - - - ns_table: dict of name->namespaces for search. - - Optional arguments: - - - ns_search: list of namespace names to include in search. - - - ignore_case(False): make the search case-insensitive. - - - show_all(False): show all names, including those starting with - underscores. - - - list_types(False): list all available object types for object matching. - """ - #print 'ps pattern:<%r>' % pattern # dbg - - # defaults - type_pattern = 'all' - filter = '' - - # list all object types - if list_types: - page.page('\n'.join(sorted(typestr2type))) - return - - cmds = pattern.split() - len_cmds = len(cmds) - if len_cmds == 1: - # Only filter pattern given - filter = cmds[0] - elif len_cmds == 2: - # Both filter and type specified - filter,type_pattern = cmds - else: - raise ValueError('invalid argument string for psearch: <%s>' % - pattern) - - # filter search namespaces - for name in ns_search: - if name not in ns_table: - raise ValueError('invalid namespace <%s>. Valid names: %s' % - (name,ns_table.keys())) - - #print 'type_pattern:',type_pattern # dbg - search_result, namespaces_seen = set(), set() - for ns_name in ns_search: - ns = ns_table[ns_name] - # Normally, locals and globals are the same, so we just check one. - if id(ns) in namespaces_seen: - continue - namespaces_seen.add(id(ns)) - tmp_res = list_namespace(ns, type_pattern, filter, - ignore_case=ignore_case, show_all=show_all) - search_result.update(tmp_res) - - page.page('\n'.join(sorted(search_result))) - - -def _render_signature(obj_signature, obj_name) -> str: - """ - This was mostly taken from inspect.Signature.__str__. - Look there for the comments. - The only change is to add linebreaks when this gets too long. - """ - result = [] - pos_only = False - kw_only = True - for param in obj_signature.parameters.values(): - if param.kind == inspect._POSITIONAL_ONLY: - pos_only = True - elif pos_only: - result.append('/') - pos_only = False - - if param.kind == inspect._VAR_POSITIONAL: - kw_only = False - elif param.kind == inspect._KEYWORD_ONLY and kw_only: - result.append('*') - kw_only = False - - result.append(str(param)) - - if pos_only: - result.append('/') - - # add up name, parameters, braces (2), and commas - if len(obj_name) + sum(len(r) + 2 for r in result) > 75: - # This doesn’t fit behind “Signature: ” in an inspect window. - rendered = '{}(\n{})'.format(obj_name, ''.join( - ' {},\n'.format(r) for r in result) - ) - else: - rendered = '{}({})'.format(obj_name, ', '.join(result)) - - if obj_signature.return_annotation is not inspect._empty: - anno = inspect.formatannotation(obj_signature.return_annotation) - rendered += ' -> {}'.format(anno) - - return rendered diff --git a/contrib/python/ipython/py3/IPython/core/page.py b/contrib/python/ipython/py3/IPython/core/page.py deleted file mode 100644 index d3e6a9eef5..0000000000 --- a/contrib/python/ipython/py3/IPython/core/page.py +++ /dev/null @@ -1,348 +0,0 @@ -# encoding: utf-8 -""" -Paging capabilities for IPython.core - -Notes ------ - -For now this uses IPython hooks, so it can't be in IPython.utils. If we can get -rid of that dependency, we could move it there. ------ -""" - -# Copyright (c) IPython Development Team. -# Distributed under the terms of the Modified BSD License. - - -import os -import io -import re -import sys -import tempfile -import subprocess - -from io import UnsupportedOperation -from pathlib import Path - -from IPython import get_ipython -from IPython.display import display -from IPython.core.error import TryNext -from IPython.utils.data import chop -from IPython.utils.process import system -from IPython.utils.terminal import get_terminal_size -from IPython.utils import py3compat - - -def display_page(strng, start=0, screen_lines=25): - """Just display, no paging. screen_lines is ignored.""" - if isinstance(strng, dict): - data = strng - else: - if start: - strng = u'\n'.join(strng.splitlines()[start:]) - data = { 'text/plain': strng } - display(data, raw=True) - - -def as_hook(page_func): - """Wrap a pager func to strip the `self` arg - - so it can be called as a hook. - """ - return lambda self, *args, **kwargs: page_func(*args, **kwargs) - - -esc_re = re.compile(r"(\x1b[^m]+m)") - -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', '') - out_ln = strng.splitlines()[start:] - screens = chop(out_ln,screen_lines-1) - if len(screens) == 1: - print(os.linesep.join(screens[0])) - else: - last_escape = "" - for scr in screens[0:-1]: - hunk = os.linesep.join(scr) - 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])) - -def _detect_screen_size(screen_lines_def): - """Attempt to work out the number of lines on the screen. - - This is called by page(). It can raise an error (e.g. when run in the - test suite), so it's separated out so it can easily be called in a try block. - """ - TERM = os.environ.get('TERM',None) - if not((TERM=='xterm' or TERM=='xterm-color') and sys.platform != 'sunos5'): - # curses causes problems on many terminals other than xterm, and - # some termios calls lock up on Sun OS5. - return screen_lines_def - - try: - import termios - import curses - except ImportError: - return screen_lines_def - - # There is a bug in curses, where *sometimes* it fails to properly - # initialize, and then after the endwin() call is made, the - # terminal is left in an unusable state. Rather than trying to - # check every time for this (by requesting and comparing termios - # flags each time), we just save the initial terminal state and - # unconditionally reset it every time. It's cheaper than making - # the checks. - try: - term_flags = termios.tcgetattr(sys.stdout) - except termios.error as err: - # can fail on Linux 2.6, pager_page will catch the TypeError - raise TypeError('termios error: {0}'.format(err)) from err - - try: - scr = curses.initscr() - except AttributeError: - # Curses on Solaris may not be complete, so we can't use it there - return screen_lines_def - - screen_lines_real,screen_cols = scr.getmaxyx() - curses.endwin() - - # Restore terminal state in case endwin() didn't. - termios.tcsetattr(sys.stdout,termios.TCSANOW,term_flags) - # Now we have what we needed: the screen size in rows/columns - return screen_lines_real - #print '***Screen size:',screen_lines_real,'lines x',\ - #screen_cols,'columns.' # dbg - -def pager_page(strng, start=0, screen_lines=0, pager_cmd=None): - """Display a string, piping through a pager after a certain length. - - strng can be a mime-bundle dict, supplying multiple representations, - keyed by mime-type. - - The screen_lines parameter specifies the number of *usable* lines of your - terminal screen (total lines minus lines you need to reserve to show other - information). - - If you set screen_lines to a number <=0, page() will try to auto-determine - your screen size and will only use up to (screen_size+screen_lines) for - printing, paging after that. That is, if you want auto-detection but need - to reserve the bottom 3 lines of the screen, use screen_lines = -3, and for - auto-detection without any lines reserved simply use screen_lines = 0. - - If a string won't fit in the allowed lines, it is sent through the - specified pager command. If none given, look for PAGER in the environment, - and ultimately default to less. - - If no system pager works, the string is sent through a 'dumb pager' - written in python, very simplistic. - """ - - # for compatibility with mime-bundle form: - if isinstance(strng, dict): - strng = strng['text/plain'] - - # Ugly kludge, but calling curses.initscr() flat out crashes in emacs - TERM = os.environ.get('TERM','dumb') - if TERM in ['dumb','emacs'] and os.name != 'nt': - print(strng) - return - # chop off the topmost part of the string we don't want to see - str_lines = strng.splitlines()[start:] - str_toprint = os.linesep.join(str_lines) - num_newlines = len(str_lines) - len_str = len(str_toprint) - - # Dumb heuristics to guesstimate number of on-screen lines the string - # takes. Very basic, but good enough for docstrings in reasonable - # terminals. If someone later feels like refining it, it's not hard. - numlines = max(num_newlines,int(len_str/80)+1) - - screen_lines_def = get_terminal_size()[1] - - # auto-determine screen size - if screen_lines <= 0: - try: - screen_lines += _detect_screen_size(screen_lines_def) - except (TypeError, UnsupportedOperation): - print(str_toprint) - return - - #print 'numlines',numlines,'screenlines',screen_lines # dbg - if numlines <= screen_lines : - #print '*** normal print' # dbg - 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 - # value of a failed system command. If any intermediate attempt - # sets retval to 1, at the end we resort to our own page_dumb() pager. - pager_cmd = get_pager_cmd(pager_cmd) - pager_cmd += ' ' + get_pager_start(pager_cmd,start) - if os.name == 'nt': - if pager_cmd.startswith('type'): - # The default WinXP 'type' command is failing on complex strings. - retval = 1 - else: - fd, tmpname = tempfile.mkstemp('.txt') - tmppath = Path(tmpname) - try: - os.close(fd) - with tmppath.open("wt", encoding="utf-8") as tmpfile: - tmpfile.write(strng) - cmd = "%s < %s" % (pager_cmd, tmppath) - # tmpfile needs to be closed for windows - if os.system(cmd): - retval = 1 - else: - retval = None - finally: - Path.unlink(tmppath) - else: - try: - retval = None - # Emulate os.popen, but redirect stderr - proc = subprocess.Popen( - pager_cmd, - shell=True, - stdin=subprocess.PIPE, - stderr=subprocess.DEVNULL, - ) - pager = os._wrap_close( - io.TextIOWrapper(proc.stdin, encoding="utf-8"), proc - ) - try: - pager_encoding = pager.encoding or sys.stdout.encoding - pager.write(strng) - finally: - retval = pager.close() - except IOError as msg: # broken pipe when user quits - if msg.args == (32, 'Broken pipe'): - retval = None - else: - retval = 1 - except OSError: - # Other strange problems, sometimes seen in Win2k/cygwin - retval = 1 - if retval is not None: - page_dumb(strng,screen_lines=screen_lines) - - -def page(data, start=0, screen_lines=0, pager_cmd=None): - """Display content in a pager, piping through a pager after a certain length. - - data can be a mime-bundle dict, supplying multiple representations, - keyed by mime-type, or text. - - Pager is dispatched via the `show_in_pager` IPython hook. - If no hook is registered, `pager_page` will be used. - """ - # Some routines may auto-compute start offsets incorrectly and pass a - # negative value. Offset to 0 for robustness. - start = max(0, start) - - # first, try the hook - ip = get_ipython() - if ip: - try: - ip.hooks.show_in_pager(data, start=start, screen_lines=screen_lines) - return - except TryNext: - pass - - # fallback on default pager - return pager_page(data, start, screen_lines, pager_cmd) - - -def page_file(fname, start=0, pager_cmd=None): - """Page a file, using an optional pager command and starting line. - """ - - pager_cmd = get_pager_cmd(pager_cmd) - pager_cmd += ' ' + get_pager_start(pager_cmd,start) - - try: - if os.environ['TERM'] in ['emacs','dumb']: - raise EnvironmentError - system(pager_cmd + ' ' + fname) - except: - try: - if start > 0: - start -= 1 - page(open(fname, encoding="utf-8").read(), start) - except: - print('Unable to show file',repr(fname)) - - -def get_pager_cmd(pager_cmd=None): - """Return a pager command. - - Makes some attempts at finding an OS-correct one. - """ - if os.name == 'posix': - default_pager_cmd = 'less -R' # -R for color control sequences - elif os.name in ['nt','dos']: - default_pager_cmd = 'type' - - if pager_cmd is None: - try: - 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' - - return pager_cmd - - -def get_pager_start(pager, start): - """Return the string for paging files with an offset. - - This is the '+N' argument which less and more (under Unix) accept. - """ - - if pager in ['less','more']: - if start: - start_string = '+' + str(start) - else: - start_string = '' - else: - start_string = '' - return start_string - - -# (X)emacs on win32 doesn't like to be bypassed with msvcrt.getch() -if os.name == 'nt' and os.environ.get('TERM','dumb') != 'emacs': - import msvcrt - def page_more(): - """ Smart pausing between pages - - @return: True if need print more lines, False if 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) - return result -else: - def page_more(): - ans = py3compat.input('---Return to continue, q to quit--- ') - if ans.lower().startswith('q'): - return False - else: - return True diff --git a/contrib/python/ipython/py3/IPython/core/payload.py b/contrib/python/ipython/py3/IPython/core/payload.py deleted file mode 100644 index 6818be1537..0000000000 --- a/contrib/python/ipython/py3/IPython/core/payload.py +++ /dev/null @@ -1,55 +0,0 @@ -# -*- coding: utf-8 -*- -"""Payload system for IPython. - -Authors: - -* Fernando Perez -* Brian Granger -""" - -#----------------------------------------------------------------------------- -# Copyright (C) 2008-2011 The IPython Development Team -# -# Distributed under the terms of the BSD License. The full license is in -# the file COPYING, distributed as part of this software. -#----------------------------------------------------------------------------- - -#----------------------------------------------------------------------------- -# Imports -#----------------------------------------------------------------------------- - -from traitlets.config.configurable import Configurable -from traitlets import List - -#----------------------------------------------------------------------------- -# Main payload class -#----------------------------------------------------------------------------- - -class PayloadManager(Configurable): - - _payload = List([]) - - def write_payload(self, data, single=True): - """Include or update the specified `data` payload in the PayloadManager. - - If a previous payload with the same source exists and `single` is True, - it will be overwritten with the new one. - """ - - if not isinstance(data, dict): - raise TypeError('Each payload write must be a dict, got: %r' % data) - - if single and 'source' in data: - source = data['source'] - for i, pl in enumerate(self._payload): - if 'source' in pl and pl['source'] == source: - self._payload[i] = data - return - - self._payload.append(data) - - def read_payload(self): - return self._payload - - def clear_payload(self): - self._payload = [] diff --git a/contrib/python/ipython/py3/IPython/core/payloadpage.py b/contrib/python/ipython/py3/IPython/core/payloadpage.py deleted file mode 100644 index 4958108076..0000000000 --- a/contrib/python/ipython/py3/IPython/core/payloadpage.py +++ /dev/null @@ -1,51 +0,0 @@ -# encoding: utf-8 -"""A payload based version of page.""" - -# Copyright (c) IPython Development Team. -# Distributed under the terms of the Modified BSD License. - -import warnings -from IPython.core.getipython import get_ipython - - -def page(strng, start=0, screen_lines=0, pager_cmd=None): - """Print a string, piping through a pager. - - This version ignores the screen_lines and pager_cmd arguments and uses - IPython's payload system instead. - - Parameters - ---------- - strng : str or mime-dict - Text to page, or a mime-type keyed dict of already formatted data. - start : int - Starting line at which to place the display. - """ - - # Some routines may auto-compute start offsets incorrectly and pass a - # negative value. Offset to 0 for robustness. - start = max(0, start) - shell = get_ipython() - - if isinstance(strng, dict): - data = strng - else: - data = {'text/plain' : strng} - payload = dict( - source='page', - data=data, - start=start, - ) - shell.payload_manager.write_payload(payload) - - -def install_payload_page(): - """DEPRECATED, use show_in_pager hook - - Install this version of page as IPython.core.page.page. - """ - warnings.warn("""install_payload_page is deprecated. - Use `ip.set_hook('show_in_pager, page.as_hook(payloadpage.page))` - """) - from IPython.core import page as corepage - corepage.page = page diff --git a/contrib/python/ipython/py3/IPython/core/prefilter.py b/contrib/python/ipython/py3/IPython/core/prefilter.py deleted file mode 100644 index 0038e5c673..0000000000 --- a/contrib/python/ipython/py3/IPython/core/prefilter.py +++ /dev/null @@ -1,698 +0,0 @@ -# encoding: utf-8 -""" -Prefiltering components. - -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. - -from keyword import iskeyword -import re - -from .autocall import IPyAutocall -from traitlets.config.configurable import Configurable -from .inputtransformer2 import ( - ESC_MAGIC, - ESC_QUOTE, - ESC_QUOTE2, - ESC_PAREN, -) -from .macro import Macro -from .splitinput import LineInfo - -from traitlets import ( - List, Integer, Unicode, Bool, Instance, CRegExp -) - -#----------------------------------------------------------------------------- -# Global utilities, errors and constants -#----------------------------------------------------------------------------- - - -class PrefilterError(Exception): - pass - - -# RegExp to identify potential function names -re_fun_name = re.compile(r'[^\W\d]([\w.]*) *$') - -# RegExp to exclude strings with this start from autocalling. In -# particular, all binary operators should be excluded, so that if foo is -# callable, foo OP bar doesn't become foo(OP bar), which is invalid. The -# characters '!=()' don't need to be checked for, as the checkPythonChars -# routine explicitly does so, to catch direct calls and rebindings of -# existing names. - -# Warning: the '-' HAS TO BE AT THE END of the first group, otherwise -# it affects the rest of the group in square brackets. -re_exclude_auto = re.compile(r'^[,&^\|\*/\+-]' - r'|^is |^not |^in |^and |^or ') - -# try to catch also methods for stuff in lists/tuples/dicts: off -# (experimental). For this to work, the line_split regexp would need -# to be modified so it wouldn't break things at '['. That line is -# nasty enough that I shouldn't change it until I can test it _well_. -#self.re_fun_name = re.compile (r'[a-zA-Z_]([a-zA-Z0-9_.\[\]]*) ?$') - - -# Handler Check Utilities -def is_shadowed(identifier, ip): - """Is the given identifier defined in one of the namespaces which shadow - the alias and magic namespaces? Note that an identifier is different - than ifun, because it can not contain a '.' character.""" - # This is much safer than calling ofind, which can change state - return (identifier in ip.user_ns \ - or identifier in ip.user_global_ns \ - or identifier in ip.ns_table['builtin']\ - or iskeyword(identifier)) - - -#----------------------------------------------------------------------------- -# Main Prefilter manager -#----------------------------------------------------------------------------- - - -class PrefilterManager(Configurable): - """Main prefilter component. - - The IPython prefilter is run on all user input before it is run. The - prefilter consumes lines of input and produces transformed lines of - input. - - The implementation consists of two phases: - - 1. Transformers - 2. Checkers and handlers - - Over time, we plan on deprecating the checkers and handlers and doing - everything in the transformers. - - The transformers are instances of :class:`PrefilterTransformer` and have - a single method :meth:`transform` that takes a line and returns a - transformed line. The transformation can be accomplished using any - tool, but our current ones use regular expressions for speed. - - After all the transformers have been run, the line is fed to the checkers, - which are instances of :class:`PrefilterChecker`. The line is passed to - the :meth:`check` method, which either returns `None` or a - :class:`PrefilterHandler` instance. If `None` is returned, the other - checkers are tried. If an :class:`PrefilterHandler` instance is returned, - the line is passed to the :meth:`handle` method of the returned - handler and no further checkers are tried. - - Both transformers and checkers have a `priority` attribute, that determines - the order in which they are called. Smaller priorities are tried first. - - Both transformers and checkers also have `enabled` attribute, which is - a boolean that determines if the instance is used. - - Users or developers can change the priority or enabled attribute of - transformers or checkers, but they must call the :meth:`sort_checkers` - or :meth:`sort_transformers` method after changing the priority. - """ - - multi_line_specials = Bool(True).tag(config=True) - shell = Instance('IPython.core.interactiveshell.InteractiveShellABC', allow_none=True) - - def __init__(self, shell=None, **kwargs): - super(PrefilterManager, self).__init__(shell=shell, **kwargs) - self.shell = shell - self._transformers = [] - self.init_handlers() - self.init_checkers() - - #------------------------------------------------------------------------- - # API for managing transformers - #------------------------------------------------------------------------- - - def sort_transformers(self): - """Sort the transformers by priority. - - This must be called after the priority of a transformer is changed. - The :meth:`register_transformer` method calls this automatically. - """ - self._transformers.sort(key=lambda x: x.priority) - - @property - def transformers(self): - """Return a list of checkers, sorted by priority.""" - return self._transformers - - def register_transformer(self, transformer): - """Register a transformer instance.""" - if transformer not in self._transformers: - self._transformers.append(transformer) - self.sort_transformers() - - def unregister_transformer(self, transformer): - """Unregister a transformer instance.""" - if transformer in self._transformers: - self._transformers.remove(transformer) - - #------------------------------------------------------------------------- - # API for managing checkers - #------------------------------------------------------------------------- - - def init_checkers(self): - """Create the default checkers.""" - self._checkers = [] - for checker in _default_checkers: - checker( - shell=self.shell, prefilter_manager=self, parent=self - ) - - def sort_checkers(self): - """Sort the checkers by priority. - - This must be called after the priority of a checker is changed. - The :meth:`register_checker` method calls this automatically. - """ - self._checkers.sort(key=lambda x: x.priority) - - @property - def checkers(self): - """Return a list of checkers, sorted by priority.""" - return self._checkers - - def register_checker(self, checker): - """Register a checker instance.""" - if checker not in self._checkers: - self._checkers.append(checker) - self.sort_checkers() - - def unregister_checker(self, checker): - """Unregister a checker instance.""" - if checker in self._checkers: - self._checkers.remove(checker) - - #------------------------------------------------------------------------- - # API for managing handlers - #------------------------------------------------------------------------- - - def init_handlers(self): - """Create the default handlers.""" - self._handlers = {} - self._esc_handlers = {} - for handler in _default_handlers: - handler( - shell=self.shell, prefilter_manager=self, parent=self - ) - - @property - def handlers(self): - """Return a dict of all the handlers.""" - return self._handlers - - def register_handler(self, name, handler, esc_strings): - """Register a handler instance by name with esc_strings.""" - self._handlers[name] = handler - for esc_str in esc_strings: - self._esc_handlers[esc_str] = handler - - def unregister_handler(self, name, handler, esc_strings): - """Unregister a handler instance by name with esc_strings.""" - try: - del self._handlers[name] - except KeyError: - pass - for esc_str in esc_strings: - h = self._esc_handlers.get(esc_str) - if h is handler: - del self._esc_handlers[esc_str] - - def get_handler_by_name(self, name): - """Get a handler by its name.""" - return self._handlers.get(name) - - def get_handler_by_esc(self, esc_str): - """Get a handler by its escape string.""" - return self._esc_handlers.get(esc_str) - - #------------------------------------------------------------------------- - # Main prefiltering API - #------------------------------------------------------------------------- - - def prefilter_line_info(self, line_info): - """Prefilter a line that has been converted to a LineInfo object. - - This implements the checker/handler part of the prefilter pipe. - """ - # print "prefilter_line_info: ", line_info - handler = self.find_handler(line_info) - return handler.handle(line_info) - - def find_handler(self, line_info): - """Find a handler for the line_info by trying checkers.""" - for checker in self.checkers: - if checker.enabled: - handler = checker.check(line_info) - if handler: - return handler - return self.get_handler_by_name('normal') - - def transform_line(self, line, continue_prompt): - """Calls the enabled transformers in order of increasing priority.""" - for transformer in self.transformers: - if transformer.enabled: - line = transformer.transform(line, continue_prompt) - return line - - def prefilter_line(self, line, continue_prompt=False): - """Prefilter a single input line as text. - - This method prefilters a single line of text by calling the - transformers and then the checkers/handlers. - """ - - # print "prefilter_line: ", line, continue_prompt - # All handlers *must* return a value, even if it's blank (''). - - # save the line away in case we crash, so the post-mortem handler can - # record it - self.shell._last_input_line = line - - if not line: - # Return immediately on purely empty lines, so that if the user - # previously typed some whitespace that started a continuation - # prompt, he can break out of that loop with just an empty line. - # This is how the default python prompt works. - return '' - - # At this point, we invoke our transformers. - if not continue_prompt or (continue_prompt and self.multi_line_specials): - line = self.transform_line(line, continue_prompt) - - # Now we compute line_info for the checkers and handlers - line_info = LineInfo(line, continue_prompt) - - # the input history needs to track even empty lines - stripped = line.strip() - - normal_handler = self.get_handler_by_name('normal') - if not stripped: - return normal_handler.handle(line_info) - - # special handlers are only allowed for single line statements - if continue_prompt and not self.multi_line_specials: - return normal_handler.handle(line_info) - - prefiltered = self.prefilter_line_info(line_info) - # print "prefiltered line: %r" % prefiltered - return prefiltered - - def prefilter_lines(self, lines, continue_prompt=False): - """Prefilter multiple input lines of text. - - This is the main entry point for prefiltering multiple lines of - input. This simply calls :meth:`prefilter_line` for each line of - input. - - This covers cases where there are multiple lines in the user entry, - which is the case when the user goes back to a multiline history - entry and presses enter. - """ - llines = lines.rstrip('\n').split('\n') - # We can get multiple lines in one shot, where multiline input 'blends' - # into one line, in cases like recalling from the readline history - # buffer. We need to make sure that in such cases, we correctly - # communicate downstream which line is first and which are continuation - # ones. - if len(llines) > 1: - out = '\n'.join([self.prefilter_line(line, lnum>0) - for lnum, line in enumerate(llines) ]) - else: - out = self.prefilter_line(llines[0], continue_prompt) - - return out - -#----------------------------------------------------------------------------- -# Prefilter transformers -#----------------------------------------------------------------------------- - - -class PrefilterTransformer(Configurable): - """Transform a line of user input.""" - - 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) - - def __init__(self, shell=None, prefilter_manager=None, **kwargs): - super(PrefilterTransformer, self).__init__( - shell=shell, prefilter_manager=prefilter_manager, **kwargs - ) - self.prefilter_manager.register_transformer(self) - - def transform(self, line, continue_prompt): - """Transform a line, returning the new one.""" - return None - - def __repr__(self): - return "<%s(priority=%r, enabled=%r)>" % ( - self.__class__.__name__, self.priority, self.enabled) - - -#----------------------------------------------------------------------------- -# Prefilter checkers -#----------------------------------------------------------------------------- - - -class PrefilterChecker(Configurable): - """Inspect an input line and return a handler for that line.""" - - 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) - - def __init__(self, shell=None, prefilter_manager=None, **kwargs): - super(PrefilterChecker, self).__init__( - shell=shell, prefilter_manager=prefilter_manager, **kwargs - ) - self.prefilter_manager.register_checker(self) - - def check(self, line_info): - """Inspect line_info and return a handler instance or None.""" - return None - - def __repr__(self): - return "<%s(priority=%r, enabled=%r)>" % ( - self.__class__.__name__, self.priority, self.enabled) - - -class EmacsChecker(PrefilterChecker): - - priority = Integer(100).tag(config=True) - enabled = Bool(False).tag(config=True) - - def check(self, line_info): - "Emacs ipython-mode tags certain input lines." - if line_info.line.endswith('# PYTHON-MODE'): - return self.prefilter_manager.get_handler_by_name('emacs') - else: - return None - - -class MacroChecker(PrefilterChecker): - - priority = Integer(250).tag(config=True) - - def check(self, line_info): - obj = self.shell.user_ns.get(line_info.ifun) - if isinstance(obj, Macro): - return self.prefilter_manager.get_handler_by_name('macro') - else: - return None - - -class IPyAutocallChecker(PrefilterChecker): - - priority = Integer(300).tag(config=True) - - def check(self, line_info): - "Instances of IPyAutocall in user_ns get autocalled immediately" - obj = self.shell.user_ns.get(line_info.ifun, None) - if isinstance(obj, IPyAutocall): - obj.set_ip(self.shell) - return self.prefilter_manager.get_handler_by_name('auto') - else: - return None - - -class AssignmentChecker(PrefilterChecker): - - 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 - which case we want to avoid any sort of automagic / autocall games. - - This allows users to assign to either alias or magic names true python - variables (the magic/alias systems always take second seat to true - python code). E.g. ls='hi', or ls,that=1,2""" - if line_info.the_rest: - if line_info.the_rest[0] in '=,': - return self.prefilter_manager.get_handler_by_name('normal') - else: - return None - - -class AutoMagicChecker(PrefilterChecker): - - priority = Integer(700).tag(config=True) - - def check(self, line_info): - """If the ifun is magic, and automagic is on, run it. Note: normal, - non-auto magic would already have been triggered via '%' in - check_esc_chars. This just checks for automagic. Also, before - triggering the magic handler, make sure that there is nothing in the - user namespace which could shadow it.""" - if not self.shell.automagic or not self.shell.find_magic(line_info.ifun): - return None - - # We have a likely magic method. Make sure we should actually call it. - if line_info.continue_prompt and not self.prefilter_manager.multi_line_specials: - return None - - head = line_info.ifun.split('.',1)[0] - if is_shadowed(head, self.shell): - return None - - return self.prefilter_manager.get_handler_by_name('magic') - - -class PythonOpsChecker(PrefilterChecker): - - 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 - any python operator, we should simply execute the line (regardless of - whether or not there's a possible autocall expansion). This avoids - spurious (and very confusing) geattr() accesses.""" - if line_info.the_rest and line_info.the_rest[0] in '!=()<>,+*/%^&|': - return self.prefilter_manager.get_handler_by_name('normal') - else: - return None - - -class AutocallChecker(PrefilterChecker): - - 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) - - def check(self, line_info): - "Check if the initial word/function is callable and autocall is on." - if not self.shell.autocall: - return None - - oinfo = line_info.ofind(self.shell) # This can mutate state via getattr - if not oinfo['found']: - return None - - ignored_funs = ['b', 'f', 'r', 'u', 'br', 'rb', 'fr', 'rf'] - ifun = line_info.ifun - line = line_info.line - if ifun.lower() in ignored_funs and (line.startswith(ifun + "'") or line.startswith(ifun + '"')): - return None - - if callable(oinfo['obj']) \ - and (not self.exclude_regexp.match(line_info.the_rest)) \ - and self.function_name_regexp.match(line_info.ifun): - return self.prefilter_manager.get_handler_by_name('auto') - else: - return None - - -#----------------------------------------------------------------------------- -# Prefilter handlers -#----------------------------------------------------------------------------- - - -class PrefilterHandler(Configurable): - - handler_name = Unicode('normal') - esc_strings = List([]) - shell = Instance('IPython.core.interactiveshell.InteractiveShellABC', allow_none=True) - prefilter_manager = Instance('IPython.core.prefilter.PrefilterManager', allow_none=True) - - def __init__(self, shell=None, prefilter_manager=None, **kwargs): - super(PrefilterHandler, self).__init__( - shell=shell, prefilter_manager=prefilter_manager, **kwargs - ) - self.prefilter_manager.register_handler( - self.handler_name, - self, - self.esc_strings - ) - - def handle(self, line_info): - # print "normal: ", line_info - """Handle normal input lines. Use as a template for handlers.""" - - # With autoindent on, we need some way to exit the input loop, and I - # don't want to force the user to have to backspace all the way to - # clear the line. The rule will be in this case, that either two - # lines of pure whitespace in a row, or a line of pure whitespace but - # of a size different to the indent level, will exit the input loop. - line = line_info.line - continue_prompt = line_info.continue_prompt - - if (continue_prompt and - self.shell.autoindent and - line.isspace() and - 0 < abs(len(line) - self.shell.indent_current_nsp) <= 2): - line = '' - - return line - - def __str__(self): - return "<%s(name=%s)>" % (self.__class__.__name__, self.handler_name) - - -class MacroHandler(PrefilterHandler): - handler_name = Unicode("macro") - - def handle(self, line_info): - obj = self.shell.user_ns.get(line_info.ifun) - pre_space = line_info.pre_whitespace - line_sep = "\n" + pre_space - return pre_space + line_sep.join(obj.value.splitlines()) - - -class MagicHandler(PrefilterHandler): - - handler_name = Unicode('magic') - esc_strings = List([ESC_MAGIC]) - - def handle(self, line_info): - """Execute magic functions.""" - ifun = line_info.ifun - the_rest = line_info.the_rest - #Prepare arguments for get_ipython().run_line_magic(magic_name, magic_args) - t_arg_s = ifun + " " + the_rest - t_magic_name, _, t_magic_arg_s = t_arg_s.partition(' ') - t_magic_name = t_magic_name.lstrip(ESC_MAGIC) - cmd = '%sget_ipython().run_line_magic(%r, %r)' % (line_info.pre_whitespace, t_magic_name, t_magic_arg_s) - return cmd - - -class AutoHandler(PrefilterHandler): - - handler_name = Unicode('auto') - esc_strings = List([ESC_PAREN, ESC_QUOTE, ESC_QUOTE2]) - - def handle(self, line_info): - """Handle lines which can be auto-executed, quoting if requested.""" - line = line_info.line - ifun = line_info.ifun - the_rest = line_info.the_rest - esc = line_info.esc - continue_prompt = line_info.continue_prompt - obj = line_info.ofind(self.shell)['obj'] - - # This should only be active for single-line input! - if continue_prompt: - return line - - force_auto = isinstance(obj, IPyAutocall) - - # User objects sometimes raise exceptions on attribute access other - # than AttributeError (we've seen it in the past), so it's safest to be - # ultra-conservative here and catch all. - try: - auto_rewrite = obj.rewrite - except Exception: - auto_rewrite = True - - if esc == ESC_QUOTE: - # Auto-quote splitting on whitespace - newcmd = '%s("%s")' % (ifun,'", "'.join(the_rest.split()) ) - elif esc == ESC_QUOTE2: - # Auto-quote whole string - newcmd = '%s("%s")' % (ifun,the_rest) - elif esc == ESC_PAREN: - newcmd = '%s(%s)' % (ifun,",".join(the_rest.split())) - else: - # Auto-paren. - if force_auto: - # Don't rewrite if it is already a call. - do_rewrite = not the_rest.startswith('(') - else: - if not the_rest: - # We only apply it to argument-less calls if the autocall - # parameter is set to 2. - do_rewrite = (self.shell.autocall >= 2) - elif the_rest.startswith('[') and hasattr(obj, '__getitem__'): - # Don't autocall in this case: item access for an object - # which is BOTH callable and implements __getitem__. - do_rewrite = False - else: - do_rewrite = True - - # Figure out the rewritten command - if do_rewrite: - if the_rest.endswith(';'): - newcmd = '%s(%s);' % (ifun.rstrip(),the_rest[:-1]) - else: - newcmd = '%s(%s)' % (ifun.rstrip(), the_rest) - else: - normal_handler = self.prefilter_manager.get_handler_by_name('normal') - return normal_handler.handle(line_info) - - # Display the rewritten call - if auto_rewrite: - self.shell.auto_rewrite_input(newcmd) - - return newcmd - - -class EmacsHandler(PrefilterHandler): - - handler_name = Unicode('emacs') - esc_strings = List([]) - - def handle(self, line_info): - """Handle input lines marked by python-mode.""" - - # Currently, nothing is done. Later more functionality can be added - # here if needed. - - # The input cache shouldn't be updated - return line_info.line - - -#----------------------------------------------------------------------------- -# Defaults -#----------------------------------------------------------------------------- - - -_default_checkers = [ - EmacsChecker, - MacroChecker, - IPyAutocallChecker, - AssignmentChecker, - AutoMagicChecker, - PythonOpsChecker, - AutocallChecker -] - -_default_handlers = [ - PrefilterHandler, - MacroHandler, - MagicHandler, - AutoHandler, - EmacsHandler -] diff --git a/contrib/python/ipython/py3/IPython/core/profile/README_STARTUP b/contrib/python/ipython/py3/IPython/core/profile/README_STARTUP deleted file mode 100644 index 61d4700042..0000000000 --- a/contrib/python/ipython/py3/IPython/core/profile/README_STARTUP +++ /dev/null @@ -1,11 +0,0 @@ -This is the IPython startup directory - -.py and .ipy files in this directory will be run *prior* to any code or files specified -via the exec_lines or exec_files configurables whenever you load this profile. - -Files will be run in lexicographical order, so you can control the execution order of files -with a prefix, e.g.:: - - 00-first.py - 50-middle.py - 99-last.ipy diff --git a/contrib/python/ipython/py3/IPython/core/profileapp.py b/contrib/python/ipython/py3/IPython/core/profileapp.py deleted file mode 100644 index 9a1bae55ac..0000000000 --- a/contrib/python/ipython/py3/IPython/core/profileapp.py +++ /dev/null @@ -1,312 +0,0 @@ -# encoding: utf-8 -""" -An application for managing IPython profiles. - -To be invoked as the `ipython profile` subcommand. - -Authors: - -* Min RK - -""" - -#----------------------------------------------------------------------------- -# Copyright (C) 2008 The IPython Development Team -# -# Distributed under the terms of the BSD License. The full license is in -# the file COPYING, distributed as part of this software. -#----------------------------------------------------------------------------- - -#----------------------------------------------------------------------------- -# Imports -#----------------------------------------------------------------------------- - -import os - -from traitlets.config.application import Application -from IPython.core.application import ( - BaseIPythonApplication, base_flags -) -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 traitlets import Unicode, Bool, Dict, observe - -#----------------------------------------------------------------------------- -# Constants -#----------------------------------------------------------------------------- - -create_help = """Create an IPython profile by name - -Create an ipython profile directory by its name or -profile directory path. Profile directories contain -configuration, log and security related files and are named -using the convention 'profile_<name>'. By default they are -located in your ipython directory. Once created, you will -can edit the configuration files in the profile -directory to configure IPython. Most users will create a -profile directory by name, -`ipython profile create myprofile`, which will put the directory -in `<ipython_dir>/profile_myprofile`. -""" -list_help = """List available IPython profiles - -List all available profiles, by profile location, that can -be found in the current working directly or in the ipython -directory. Profile directories are named using the convention -'profile_<profile>'. -""" -profile_help = """Manage IPython profiles - -Profile directories contain -configuration, log and security related files and are named -using the convention 'profile_<name>'. By default they are -located in your ipython directory. You can create profiles -with `ipython profile create <name>`, or see the profiles you -already have with `ipython profile list` - -To get started configuring IPython, simply do: - -$> ipython profile create - -and IPython will create the default profile in <ipython_dir>/profile_default, -where you can edit ipython_config.py to start configuring IPython. - -""" - -_list_examples = "ipython profile list # list all profiles" - -_create_examples = """ -ipython profile create foo # create profile foo w/ default config files -ipython profile create foo --reset # restage default config files over current -ipython profile create foo --parallel # also stage parallel config files -""" - -_main_examples = """ -ipython profile create -h # show the help string for the create subcommand -ipython profile list -h # show the help string for the list subcommand - -ipython locate profile foo # print the path to the directory for profile 'foo' -""" - -#----------------------------------------------------------------------------- -# Profile Application Class (for `ipython profile` subcommand) -#----------------------------------------------------------------------------- - - -def list_profiles_in(path): - """list profiles in a given root directory""" - profiles = [] - - # for python 3.6+ rewrite to: with os.scandir(path) as dirlist: - files = os.scandir(path) - for f in files: - if f.is_dir() and f.name.startswith('profile_'): - profiles.append(f.name.split('_', 1)[-1]) - return profiles - - -def list_bundled_profiles(): - """list profiles that are bundled with IPython.""" - path = os.path.join(get_ipython_package_dir(), u'core', u'profile') - profiles = [] - - # for python 3.6+ rewrite to: with os.scandir(path) as dirlist: - files = os.scandir(path) - for profile in files: - if profile.is_dir() and profile.name != "__pycache__": - profiles.append(profile.name) - return profiles - - -class ProfileLocate(BaseIPythonApplication): - description = """print the path to an IPython profile dir""" - - def parse_command_line(self, argv=None): - super(ProfileLocate, self).parse_command_line(argv) - if self.extra_args: - self.profile = self.extra_args[0] - - def start(self): - print(self.profile_dir.location) - - -class ProfileList(Application): - name = u'ipython-profile' - description = list_help - examples = _list_examples - - aliases = Dict({ - 'ipython-dir' : 'ProfileList.ipython_dir', - 'log-level' : 'Application.log_level', - }) - flags = Dict(dict( - debug = ({'Application' : {'log_level' : 0}}, - "Set Application.log_level to 0, maximizing log output." - ) - )) - - 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) - - - def _print_profiles(self, profiles): - """print list of profiles, indented.""" - for profile in profiles: - print(' %s' % profile) - - def list_profile_dirs(self): - profiles = list_bundled_profiles() - if profiles: - print() - print("Available profiles in IPython:") - self._print_profiles(profiles) - print() - print(" The first request for a bundled profile will copy it") - print(" into your IPython directory (%s)," % self.ipython_dir) - print(" where you can customize it.") - - profiles = list_profiles_in(self.ipython_dir) - if profiles: - print() - print("Available profiles in %s:" % self.ipython_dir) - self._print_profiles(profiles) - - profiles = list_profiles_in(os.getcwd()) - if profiles: - print() - print( - "Profiles from CWD have been removed for security reason, see CVE-2022-21699:" - ) - - print() - print("To use any of the above profiles, start IPython with:") - print(" ipython --profile=<name>") - print() - - def start(self): - self.list_profile_dirs() - - -create_flags = {} -create_flags.update(base_flags) -# don't include '--init' flag, which implies running profile create in other apps -create_flags.pop('init') -create_flags['reset'] = ({'ProfileCreate': {'overwrite' : True}}, - "reset config files in this profile to the defaults.") -create_flags['parallel'] = ({'ProfileCreate': {'parallel' : True}}, - "Include the config files for parallel " - "computing apps (ipengine, ipcontroller, etc.)") - - -class ProfileCreate(BaseIPythonApplication): - name = u'ipython-profile' - description = create_help - examples = _create_examples - 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_files = [ 'ipcontroller_config.py', - 'ipengine_config.py', - 'ipcluster_config.py' - ] - if change['new']: - for cf in parallel_files: - self.config_files.append(cf) - else: - for cf in parallel_files: - if cf in self.config_files: - self.config_files.remove(cf) - - def parse_command_line(self, argv): - super(ProfileCreate, self).parse_command_line(argv) - # accept positional arg as profile name - if self.extra_args: - self.profile = self.extra_args[0] - - flags = Dict(create_flags) - - classes = [ProfileDir] - - def _import_app(self, app_path): - """import an app class""" - app = None - name = app_path.rsplit('.', 1)[-1] - try: - app = import_item(app_path) - except ImportError: - self.log.info("Couldn't import %s, config file will be excluded", name) - except Exception: - self.log.warning('Unexpected error importing %s', name, exc_info=True) - return app - - def init_config_files(self): - super(ProfileCreate, self).init_config_files() - # use local imports, since these classes may import from here - from IPython.terminal.ipapp import TerminalIPythonApp - apps = [TerminalIPythonApp] - for app_path in ( - 'ipykernel.kernelapp.IPKernelApp', - ): - app = self._import_app(app_path) - if app is not None: - apps.append(app) - if self.parallel: - from ipyparallel.apps.ipcontrollerapp import IPControllerApp - from ipyparallel.apps.ipengineapp import IPEngineApp - from ipyparallel.apps.ipclusterapp import IPClusterStart - apps.extend([ - IPControllerApp, - IPEngineApp, - IPClusterStart, - ]) - for App in apps: - app = App() - app.config.update(self.config) - app.log = self.log - app.overwrite = self.overwrite - app.copy_config_files=True - app.ipython_dir=self.ipython_dir - app.profile_dir=self.profile_dir - app.init_config_files() - - def stage_default_config_file(self): - pass - - -class ProfileApp(Application): - name = u'ipython profile' - description = profile_help - examples = _main_examples - - subcommands = Dict(dict( - create = (ProfileCreate, ProfileCreate.description.splitlines()[0]), - list = (ProfileList, ProfileList.description.splitlines()[0]), - locate = (ProfileLocate, ProfileLocate.description.splitlines()[0]), - )) - - def start(self): - if self.subapp is None: - print("No subcommand specified. Must specify one of: %s"%(self.subcommands.keys())) - print() - self.print_description() - self.print_subcommands() - self.exit(1) - else: - return self.subapp.start() diff --git a/contrib/python/ipython/py3/IPython/core/profiledir.py b/contrib/python/ipython/py3/IPython/core/profiledir.py deleted file mode 100644 index cb4d39339a..0000000000 --- a/contrib/python/ipython/py3/IPython/core/profiledir.py +++ /dev/null @@ -1,223 +0,0 @@ -# encoding: utf-8 -"""An object for managing IPython profile directories.""" - -# Copyright (c) IPython Development Team. -# Distributed under the terms of the Modified BSD License. - -import os -import shutil -import errno -from pathlib import Path - -from traitlets.config.configurable import LoggingConfigurable -from ..paths import get_ipython_package_dir -from ..utils.path import expand_path, ensure_dir_exists -from traitlets import Unicode, Bool, observe - -#----------------------------------------------------------------------------- -# Module errors -#----------------------------------------------------------------------------- - -class ProfileDirError(Exception): - pass - - -#----------------------------------------------------------------------------- -# Class for managing profile directories -#----------------------------------------------------------------------------- - -class ProfileDir(LoggingConfigurable): - """An object to manage the profile directory and its resources. - - The profile directory is used by all IPython applications, to manage - configuration, logging and security. - - This object knows how to find, create and manage these directories. This - should be used by any code that wants to handle profiles. - """ - - security_dir_name = Unicode('security') - log_dir_name = Unicode('log') - startup_dir_name = Unicode('startup') - pid_dir_name = Unicode('pid') - static_dir_name = Unicode('static') - security_dir = Unicode(u'') - log_dir = Unicode(u'') - startup_dir = Unicode(u'') - pid_dir = Unicode(u'') - static_dir = Unicode(u'') - - location = Unicode(u'', - help="""Set the profile location directly. This overrides the logic used by the - `profile` option.""", - ).tag(config=True) - - _location_isset = Bool(False) # flag for detecting multiply set location - @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'] - ensure_dir_exists(new) - - # ensure config files exist: - self.security_dir = os.path.join(new, self.security_dir_name) - self.log_dir = os.path.join(new, self.log_dir_name) - self.startup_dir = os.path.join(new, self.startup_dir_name) - 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 - - This is a version of os.mkdir, with the following differences: - - - returns True if it created the directory, False otherwise - - ignores EEXIST, protecting against race conditions where - the dir may have been created in between the check and - the creation - - sets permissions if requested and the dir already exists - """ - if os.path.exists(path): - if mode and os.stat(path).st_mode != mode: - try: - os.chmod(path, mode) - except OSError: - self.log.warning( - "Could not set permissions on %s", - path - ) - return False - try: - if mode: - os.mkdir(path, mode) - else: - os.mkdir(path) - except OSError as e: - if e.errno == errno.EEXIST: - return False - else: - raise - - return True - - @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): - self._mkdir(self.startup_dir) - - readme = os.path.join(self.startup_dir, 'README') - - if not os.path.exists(readme): - import pkgutil - 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): - self._mkdir(self.security_dir, 0o40700) - - @observe('pid_dir') - def check_pid_dir(self, change=None): - self._mkdir(self.pid_dir, 0o40700) - - def check_dirs(self): - self.check_security_dir() - self.check_log_dir() - self.check_pid_dir() - self.check_startup_dir() - - def copy_config_file(self, config_file: str, path: Path, overwrite=False) -> bool: - """Copy a default config file into the active profile directory. - - Default configuration files are kept in :mod:`IPython.core.profile`. - This function moves these from that location to the working profile - directory. - """ - dst = Path(os.path.join(self.location, config_file)) - if dst.exists() and not overwrite: - return False - if path is None: - path = os.path.join(get_ipython_package_dir(), u'core', u'profile', u'default') - assert isinstance(path, Path) - src = path / config_file - shutil.copy(src, dst) - return True - - @classmethod - def create_profile_dir(cls, profile_dir, config=None): - """Create a new profile directory given a full path. - - Parameters - ---------- - profile_dir : str - The full path to the profile directory. If it does exist, it will - be used. If not, it will be created. - """ - return cls(location=profile_dir, config=config) - - @classmethod - def create_profile_dir_by_name(cls, path, name=u'default', config=None): - """Create a profile dir by profile name and path. - - Parameters - ---------- - path : unicode - The path (directory) to put the profile directory in. - name : unicode - The name of the profile. The name of the profile directory will - be "profile_<profile>". - """ - if not os.path.isdir(path): - raise ProfileDirError('Directory not found: %s' % path) - profile_dir = os.path.join(path, u'profile_' + name) - return cls(location=profile_dir, config=config) - - @classmethod - def find_profile_dir_by_name(cls, ipython_dir, name=u'default', config=None): - """Find an existing profile dir by profile name, return its ProfileDir. - - This searches through a sequence of paths for a profile dir. If it - is not found, a :class:`ProfileDirError` exception will be raised. - - The search path algorithm is: - 1. ``os.getcwd()`` # removed for security reason. - 2. ``ipython_dir`` - - Parameters - ---------- - ipython_dir : unicode or str - The IPython directory to use. - name : unicode or str - The name of the profile. The name of the profile directory - will be "profile_<profile>". - """ - dirname = u'profile_' + name - paths = [ipython_dir] - for p in paths: - profile_dir = os.path.join(p, dirname) - if os.path.isdir(profile_dir): - return cls(location=profile_dir, config=config) - else: - raise ProfileDirError('Profile directory not found in paths: %s' % dirname) - - @classmethod - def find_profile_dir(cls, profile_dir, config=None): - """Find/create a profile dir and return its ProfileDir. - - This will create the profile directory if it doesn't exist. - - Parameters - ---------- - profile_dir : unicode or str - The path of the profile directory. - """ - profile_dir = expand_path(profile_dir) - if not os.path.isdir(profile_dir): - raise ProfileDirError('Profile directory not found: %s' % profile_dir) - return cls(location=profile_dir, config=config) diff --git a/contrib/python/ipython/py3/IPython/core/prompts.py b/contrib/python/ipython/py3/IPython/core/prompts.py deleted file mode 100644 index 7fd218d37a..0000000000 --- a/contrib/python/ipython/py3/IPython/core/prompts.py +++ /dev/null @@ -1,21 +0,0 @@ -# -*- coding: utf-8 -*- -"""Being removed -""" - -class LazyEvaluate(object): - """This is used for formatting strings with values that need to be updated - at that time, such as the current time or working directory.""" - def __init__(self, func, *args, **kwargs): - self.func = func - self.args = args - self.kwargs = kwargs - - def __call__(self, **kwargs): - self.kwargs.update(kwargs) - return self.func(*self.args, **self.kwargs) - - def __str__(self): - return str(self()) - - def __format__(self, format_spec): - return format(self(), format_spec) diff --git a/contrib/python/ipython/py3/IPython/core/pylabtools.py b/contrib/python/ipython/py3/IPython/core/pylabtools.py deleted file mode 100644 index 68e100f7d0..0000000000 --- a/contrib/python/ipython/py3/IPython/core/pylabtools.py +++ /dev/null @@ -1,424 +0,0 @@ -# -*- coding: utf-8 -*- -"""Pylab (matplotlib) support utilities.""" - -# Copyright (c) IPython Development Team. -# Distributed under the terms of the Modified BSD License. - -from io import BytesIO -from binascii import b2a_base64 -from functools import partial -import warnings - -from IPython.core.display import _pngxy -from IPython.utils.decorators import flag_calls - -# If user specifies a GUI, that dictates the backend, otherwise we read the -# user's mpl default from the mpl rc structure -backends = { - "tk": "TkAgg", - "gtk": "GTKAgg", - "gtk3": "GTK3Agg", - "gtk4": "GTK4Agg", - "wx": "WXAgg", - "qt4": "Qt4Agg", - "qt5": "Qt5Agg", - "qt6": "QtAgg", - "qt": "Qt5Agg", - "osx": "MacOSX", - "nbagg": "nbAgg", - "notebook": "nbAgg", - "agg": "agg", - "svg": "svg", - "pdf": "pdf", - "ps": "ps", - "inline": "module://matplotlib_inline.backend_inline", - "ipympl": "module://ipympl.backend_nbagg", - "widget": "module://ipympl.backend_nbagg", -} - -# We also need a reverse backends2guis mapping that will properly choose which -# GUI support to activate based on the desired matplotlib backend. For the -# most part it's just a reverse of the above dict, but we also need to add a -# few others that map to the same GUI manually: -backend2gui = dict(zip(backends.values(), backends.keys())) -# In the reverse mapping, there are a few extra valid matplotlib backends that -# map to the same GUI support -backend2gui["GTK"] = backend2gui["GTKCairo"] = "gtk" -backend2gui["GTK3Cairo"] = "gtk3" -backend2gui["GTK4Cairo"] = "gtk4" -backend2gui["WX"] = "wx" -backend2gui["CocoaAgg"] = "osx" -# There needs to be a hysteresis here as the new QtAgg Matplotlib backend -# supports either Qt5 or Qt6 and the IPython qt event loop support Qt4, Qt5, -# and Qt6. -backend2gui["QtAgg"] = "qt" -backend2gui["Qt4Agg"] = "qt" -backend2gui["Qt5Agg"] = "qt" - -# And some backends that don't need GUI integration -del backend2gui["nbAgg"] -del backend2gui["agg"] -del backend2gui["svg"] -del backend2gui["pdf"] -del backend2gui["ps"] -del backend2gui["module://matplotlib_inline.backend_inline"] -del backend2gui["module://ipympl.backend_nbagg"] - -#----------------------------------------------------------------------------- -# Matplotlib utilities -#----------------------------------------------------------------------------- - - -def getfigs(*fig_nums): - """Get a list of matplotlib figures by figure numbers. - - If no arguments are given, all available figures are returned. If the - argument list contains references to invalid figures, a warning is printed - but the function continues pasting further figures. - - Parameters - ---------- - figs : tuple - A tuple of ints giving the figure numbers of the figures to return. - """ - from matplotlib._pylab_helpers import Gcf - if not fig_nums: - fig_managers = Gcf.get_all_fig_managers() - return [fm.canvas.figure for fm in fig_managers] - else: - figs = [] - for num in fig_nums: - f = Gcf.figs.get(num) - if f is None: - print('Warning: figure %s not available.' % num) - else: - figs.append(f.canvas.figure) - return figs - - -def figsize(sizex, sizey): - """Set the default figure size to be [sizex, sizey]. - - This is just an easy to remember, convenience wrapper that sets:: - - matplotlib.rcParams['figure.figsize'] = [sizex, sizey] - """ - import matplotlib - matplotlib.rcParams['figure.figsize'] = [sizex, sizey] - - -def print_figure(fig, fmt="png", bbox_inches="tight", base64=False, **kwargs): - """Print a figure to an image, and return the resulting file data - - Returned data will be bytes unless ``fmt='svg'``, - in which case it will be unicode. - - Any keyword args are passed to fig.canvas.print_figure, - such as ``quality`` or ``bbox_inches``. - - If `base64` is True, return base64-encoded str instead of raw bytes - for binary-encoded image formats - - .. versionadded:: 7.29 - base64 argument - """ - # When there's an empty figure, we shouldn't return anything, otherwise we - # get big blank areas in the qt console. - if not fig.axes and not fig.lines: - return - - dpi = fig.dpi - if fmt == 'retina': - dpi = dpi * 2 - fmt = 'png' - - # build keyword args - kw = { - "format":fmt, - "facecolor":fig.get_facecolor(), - "edgecolor":fig.get_edgecolor(), - "dpi":dpi, - "bbox_inches":bbox_inches, - } - # **kwargs get higher priority - kw.update(kwargs) - - bytes_io = BytesIO() - if fig.canvas is None: - from matplotlib.backend_bases import FigureCanvasBase - FigureCanvasBase(fig) - - fig.canvas.print_figure(bytes_io, **kw) - data = bytes_io.getvalue() - if fmt == 'svg': - data = data.decode('utf-8') - elif base64: - data = b2a_base64(data).decode("ascii") - return data - -def retina_figure(fig, base64=False, **kwargs): - """format a figure as a pixel-doubled (retina) PNG - - If `base64` is True, return base64-encoded str instead of raw bytes - for binary-encoded image formats - - .. versionadded:: 7.29 - base64 argument - """ - pngdata = print_figure(fig, fmt="retina", base64=False, **kwargs) - # Make sure that retina_figure acts just like print_figure and returns - # None when the figure is empty. - if pngdata is None: - return - w, h = _pngxy(pngdata) - metadata = {"width": w//2, "height":h//2} - if base64: - pngdata = b2a_base64(pngdata).decode("ascii") - return pngdata, metadata - - -# We need a little factory function here to create the closure where -# safe_execfile can live. -def mpl_runner(safe_execfile): - """Factory to return a matplotlib-enabled runner for %run. - - Parameters - ---------- - safe_execfile : function - This must be a function with the same interface as the - :meth:`safe_execfile` method of IPython. - - Returns - ------- - A function suitable for use as the ``runner`` argument of the %run magic - function. - """ - - def mpl_execfile(fname,*where,**kw): - """matplotlib-aware wrapper around safe_execfile. - - Its interface is identical to that of the :func:`execfile` builtin. - - This is ultimately a call to execfile(), but wrapped in safeties to - properly handle interactive rendering.""" - - import matplotlib - import matplotlib.pyplot as plt - - #print '*** Matplotlib runner ***' # dbg - # turn off rendering until end of script - is_interactive = matplotlib.rcParams['interactive'] - matplotlib.interactive(False) - safe_execfile(fname,*where,**kw) - matplotlib.interactive(is_interactive) - # make rendering call now, if the user tried to do it - if plt.draw_if_interactive.called: - plt.draw() - plt.draw_if_interactive.called = False - - # re-draw everything that is stale - try: - da = plt.draw_all - except AttributeError: - pass - else: - da() - - return mpl_execfile - - -def _reshow_nbagg_figure(fig): - """reshow an nbagg figure""" - try: - reshow = fig.canvas.manager.reshow - except AttributeError as e: - raise NotImplementedError() from e - else: - reshow() - - -def select_figure_formats(shell, formats, **kwargs): - """Select figure formats for the inline backend. - - Parameters - ---------- - shell : InteractiveShell - The main IPython instance. - formats : str or set - One or a set of figure formats to enable: 'png', 'retina', 'jpeg', 'svg', 'pdf'. - **kwargs : any - Extra keyword arguments to be passed to fig.canvas.print_figure. - """ - import matplotlib - from matplotlib.figure import Figure - - svg_formatter = shell.display_formatter.formatters['image/svg+xml'] - png_formatter = shell.display_formatter.formatters['image/png'] - jpg_formatter = shell.display_formatter.formatters['image/jpeg'] - pdf_formatter = shell.display_formatter.formatters['application/pdf'] - - if isinstance(formats, str): - formats = {formats} - # cast in case of list / tuple - formats = set(formats) - - [ f.pop(Figure, None) for f in shell.display_formatter.formatters.values() ] - mplbackend = matplotlib.get_backend().lower() - if mplbackend == 'nbagg' or mplbackend == 'module://ipympl.backend_nbagg': - formatter = shell.display_formatter.ipython_display_formatter - formatter.for_type(Figure, _reshow_nbagg_figure) - - supported = {'png', 'png2x', 'retina', 'jpg', 'jpeg', 'svg', 'pdf'} - bad = formats.difference(supported) - if bad: - bs = "%s" % ','.join([repr(f) for f in bad]) - gs = "%s" % ','.join([repr(f) for f in supported]) - raise ValueError("supported formats are: %s not %s" % (gs, bs)) - - if "png" in formats: - png_formatter.for_type( - Figure, partial(print_figure, fmt="png", base64=True, **kwargs) - ) - if "retina" in formats or "png2x" in formats: - png_formatter.for_type(Figure, partial(retina_figure, base64=True, **kwargs)) - if "jpg" in formats or "jpeg" in formats: - jpg_formatter.for_type( - Figure, partial(print_figure, fmt="jpg", base64=True, **kwargs) - ) - if "svg" in formats: - svg_formatter.for_type(Figure, partial(print_figure, fmt="svg", **kwargs)) - if "pdf" in formats: - pdf_formatter.for_type( - Figure, partial(print_figure, fmt="pdf", base64=True, **kwargs) - ) - -#----------------------------------------------------------------------------- -# Code for initializing matplotlib and importing pylab -#----------------------------------------------------------------------------- - - -def find_gui_and_backend(gui=None, gui_select=None): - """Given a gui string return the gui and mpl backend. - - Parameters - ---------- - gui : str - Can be one of ('tk','gtk','wx','qt','qt4','inline','agg'). - gui_select : str - Can be one of ('tk','gtk','wx','qt','qt4','inline'). - This is any gui already selected by the shell. - - Returns - ------- - A tuple of (gui, backend) where backend is one of ('TkAgg','GTKAgg', - 'WXAgg','Qt4Agg','module://matplotlib_inline.backend_inline','agg'). - """ - - import matplotlib - - if gui and gui != 'auto': - # select backend based on requested gui - backend = backends[gui] - if gui == 'agg': - gui = None - else: - # We need to read the backend from the original data structure, *not* - # from mpl.rcParams, since a prior invocation of %matplotlib may have - # overwritten that. - # WARNING: this assumes matplotlib 1.1 or newer!! - backend = matplotlib.rcParamsOrig['backend'] - # In this case, we need to find what the appropriate gui selection call - # should be for IPython, so we can activate inputhook accordingly - gui = backend2gui.get(backend, None) - - # If we have already had a gui active, we need it and inline are the - # ones allowed. - if gui_select and gui != gui_select: - gui = gui_select - backend = backends[gui] - - return gui, backend - - -def activate_matplotlib(backend): - """Activate the given backend and set interactive to True.""" - - import matplotlib - matplotlib.interactive(True) - - # Matplotlib had a bug where even switch_backend could not force - # the rcParam to update. This needs to be set *before* the module - # magic of switch_backend(). - matplotlib.rcParams['backend'] = backend - - # Due to circular imports, pyplot may be only partially initialised - # when this function runs. - # So avoid needing matplotlib attribute-lookup to access pyplot. - from matplotlib import pyplot as plt - - plt.switch_backend(backend) - - plt.show._needmain = False - # We need to detect at runtime whether show() is called by the user. - # For this, we wrap it into a decorator which adds a 'called' flag. - plt.draw_if_interactive = flag_calls(plt.draw_if_interactive) - - -def import_pylab(user_ns, import_all=True): - """Populate the namespace with pylab-related values. - - Imports matplotlib, pylab, numpy, and everything from pylab and numpy. - - Also imports a few names from IPython (figsize, display, getfigs) - - """ - - # Import numpy as np/pyplot as plt are conventions we're trying to - # somewhat standardize on. Making them available to users by default - # will greatly help this. - s = ("import numpy\n" - "import matplotlib\n" - "from matplotlib import pylab, mlab, pyplot\n" - "np = numpy\n" - "plt = pyplot\n" - ) - exec(s, user_ns) - - if import_all: - s = ("from matplotlib.pylab import *\n" - "from numpy import *\n") - exec(s, user_ns) - - # IPython symbols to add - user_ns['figsize'] = figsize - from IPython.display import display - # Add display and getfigs to the user's namespace - user_ns['display'] = display - user_ns['getfigs'] = getfigs - - -def configure_inline_support(shell, backend): - """ - .. deprecated:: 7.23 - - use `matplotlib_inline.backend_inline.configure_inline_support()` - - Configure an IPython shell object for matplotlib use. - - Parameters - ---------- - shell : InteractiveShell instance - backend : matplotlib backend - """ - warnings.warn( - "`configure_inline_support` is deprecated since IPython 7.23, directly " - "use `matplotlib_inline.backend_inline.configure_inline_support()`", - DeprecationWarning, - stacklevel=2, - ) - - from matplotlib_inline.backend_inline import ( - configure_inline_support as configure_inline_support_orig, - ) - - configure_inline_support_orig(shell, backend) diff --git a/contrib/python/ipython/py3/IPython/core/release.py b/contrib/python/ipython/py3/IPython/core/release.py deleted file mode 100644 index cda5c32d44..0000000000 --- a/contrib/python/ipython/py3/IPython/core/release.py +++ /dev/null @@ -1,54 +0,0 @@ -# -*- coding: utf-8 -*- -"""Release data for the IPython project.""" - -#----------------------------------------------------------------------------- -# Copyright (c) 2008, IPython Development Team. -# Copyright (c) 2001, Fernando Perez <fernando.perez@colorado.edu> -# Copyright (c) 2001, Janko Hauser <jhauser@zscout.de> -# Copyright (c) 2001, Nathaniel Gray <n8gray@caltech.edu> -# -# Distributed under the terms of the Modified BSD License. -# -# The full license is in the file COPYING.txt, distributed with this software. -#----------------------------------------------------------------------------- - -# 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 = 8 -_version_minor = 4 -_version_patch = 0 -_version_extra = ".dev" -# _version_extra = "rc1" -_version_extra = "" # Uncomment this for full releases - -# Construct full version string from these. -_ver = [_version_major, _version_minor, _version_patch] - -__version__ = '.'.join(map(str, _ver)) -if _version_extra: - __version__ = __version__ + _version_extra - -version = __version__ # backwards compatibility name -version_info = (_version_major, _version_minor, _version_patch, _version_extra) - -# Change this when incrementing the kernel protocol version -kernel_protocol_version_info = (5, 0) -kernel_protocol_version = "%i.%i" % kernel_protocol_version_info - -license = 'BSD' - -authors = {'Fernando' : ('Fernando Perez','fperez.net@gmail.com'), - 'Janko' : ('Janko Hauser','jhauser@zscout.de'), - 'Nathan' : ('Nathaniel Gray','n8gray@caltech.edu'), - 'Ville' : ('Ville Vainio','vivainio@gmail.com'), - 'Brian' : ('Brian E Granger', 'ellisonbg@gmail.com'), - 'Min' : ('Min Ragan-Kelley', 'benjaminrk@gmail.com'), - 'Thomas' : ('Thomas A. Kluyver', 'takowl@gmail.com'), - 'Jorgen' : ('Jorgen Stenarson', 'jorgen.stenarson@bostream.nu'), - 'Matthias' : ('Matthias Bussonnier', 'bussonniermatthias@gmail.com'), - } - -author = 'The IPython Development Team' - -author_email = 'ipython-dev@python.org' diff --git a/contrib/python/ipython/py3/IPython/core/shellapp.py b/contrib/python/ipython/py3/IPython/core/shellapp.py deleted file mode 100644 index f737bcb56b..0000000000 --- a/contrib/python/ipython/py3/IPython/core/shellapp.py +++ /dev/null @@ -1,452 +0,0 @@ -# encoding: utf-8 -""" -A mixin for :class:`~IPython.core.application.Application` classes that -launch InteractiveShell instances, load extensions, etc. -""" - -# Copyright (c) IPython Development Team. -# Distributed under the terms of the Modified BSD License. - -import glob -from itertools import chain -import os -import sys - -from traitlets.config.application import boolean_flag -from traitlets.config.configurable import Configurable -from traitlets.config.loader import Config -from IPython.core.application import SYSTEM_CONFIG_DIRS, ENV_CONFIG_DIRS -from IPython.core import pylabtools -from IPython.utils.contexts import preserve_keys -from IPython.utils.path import filefind -import traitlets -from traitlets import ( - Unicode, Instance, List, Bool, CaselessStrEnum, observe, - DottedObjectName, -) -from IPython.terminal import pt_inputhooks - -#----------------------------------------------------------------------------- -# Aliases and Flags -#----------------------------------------------------------------------------- - -gui_keys = tuple(sorted(pt_inputhooks.backends) + sorted(pt_inputhooks.aliases)) - -backend_keys = sorted(pylabtools.backends.keys()) -backend_keys.insert(0, 'auto') - -shell_flags = {} - -addflag = lambda *args: shell_flags.update(boolean_flag(*args)) -addflag('autoindent', 'InteractiveShell.autoindent', - 'Turn on autoindenting.', 'Turn off autoindenting.' -) -addflag('automagic', 'InteractiveShell.automagic', - """Turn on the auto calling of magic commands. Type %%magic at the - IPython prompt for more information.""", - 'Turn off the auto calling of magic commands.' -) -addflag('pdb', 'InteractiveShell.pdb', - "Enable auto calling the pdb debugger after every exception.", - "Disable auto calling the pdb debugger after every exception." -) -addflag('pprint', 'PlainTextFormatter.pprint', - "Enable auto pretty printing of results.", - "Disable auto pretty printing of results." -) -addflag('color-info', 'InteractiveShell.color_info', - """IPython can display information about objects via a set of functions, - and optionally can use colors for this, syntax highlighting - source code and various other elements. This is on by default, but can cause - problems with some pagers. If you see such problems, you can disable the - colours.""", - "Disable using colors for info related things." -) -addflag('ignore-cwd', 'InteractiveShellApp.ignore_cwd', - "Exclude the current working directory from sys.path", - "Include the current working directory in sys.path", -) -nosep_config = Config() -nosep_config.InteractiveShell.separate_in = '' -nosep_config.InteractiveShell.separate_out = '' -nosep_config.InteractiveShell.separate_out2 = '' - -shell_flags['nosep']=(nosep_config, "Eliminate all spacing between prompts.") -shell_flags['pylab'] = ( - {'InteractiveShellApp' : {'pylab' : 'auto'}}, - """Pre-load matplotlib and numpy for interactive use with - the default matplotlib backend.""" -) -shell_flags['matplotlib'] = ( - {'InteractiveShellApp' : {'matplotlib' : 'auto'}}, - """Configure matplotlib for interactive use with - the default matplotlib backend.""" -) - -# it's possible we don't want short aliases for *all* of these: -shell_aliases = dict( - autocall='InteractiveShell.autocall', - colors='InteractiveShell.colors', - logfile='InteractiveShell.logfile', - logappend='InteractiveShell.logappend', - c='InteractiveShellApp.code_to_run', - m='InteractiveShellApp.module_to_run', - ext="InteractiveShellApp.extra_extensions", - gui='InteractiveShellApp.gui', - pylab='InteractiveShellApp.pylab', - matplotlib='InteractiveShellApp.matplotlib', -) -shell_aliases['cache-size'] = 'InteractiveShell.cache_size' - -#----------------------------------------------------------------------------- -# Main classes and functions -#----------------------------------------------------------------------------- - -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. - - The following methods should be called by the :meth:`initialize` method - of the subclass: - - - :meth:`init_path` - - :meth:`init_shell` (to be implemented by the subclass) - - :meth:`init_gui_pylab` - - :meth:`init_extensions` - - :meth:`init_code` - """ - extensions = List(Unicode(), - help="A list of dotted module names of IPython extensions to load." - ).tag(config=True) - - extra_extensions = List( - DottedObjectName(), - help=""" - Dotted module name(s) of one or more IPython extensions to load. - - For specifying extra extensions to load on the command-line. - - .. versionadded:: 7.10 - """, - ).tag(config=True) - - reraise_ipython_extension_failures = Bool(False, - help="Reraise exceptions encountered loading IPython extensions?", - ).tag(config=True) - - # Extensions that are always loaded (not configurable) - 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) - - exec_files = List(Unicode(), - help="""List of files to run at IPython startup.""" - ).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) - - exec_lines = List(Unicode(), - help="""lines of code to run at IPython startup.""" - ).tag(config=True) - code_to_run = Unicode('', - help="Execute the given command string." - ).tag(config=True) - module_to_run = Unicode('', - help="Run the module as a script." - ).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) - matplotlib = CaselessStrEnum(backend_keys, allow_none=True, - help="""Configure matplotlib for interactive use with - the default matplotlib backend.""" - ).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, - 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) - ignore_cwd = Bool( - False, - help="""If True, IPython will not add the current working directory to sys.path. - When False, the current working directory is added to sys.path, allowing imports - of modules defined in the current directory.""" - ).tag(config=True) - shell = Instance('IPython.core.interactiveshell.InteractiveShellABC', - allow_none=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): - if self.shell is not None: - self.shell.user_ns = change['new'] - self.shell.init_user_ns() - - def init_path(self): - """Add current working directory, '', to sys.path - - Unlike Python's default, we insert before the first `site-packages` - or `dist-packages` directory, - so that it is after the standard library. - - .. versionchanged:: 7.2 - Try to insert after the standard library, instead of first. - .. versionchanged:: 8.0 - Allow optionally not including the current directory in sys.path - """ - if '' in sys.path or self.ignore_cwd: - return - for idx, path in enumerate(sys.path): - parent, last_part = os.path.split(path) - if last_part in {'site-packages', 'dist-packages'}: - break - else: - # no site-packages or dist-packages found (?!) - # back to original behavior of inserting at the front - idx = 0 - sys.path.insert(idx, '') - - def init_shell(self): - raise NotImplementedError("Override in subclasses") - - def init_gui_pylab(self): - """Enable GUI event loop integration, taking pylab into account.""" - enable = False - shell = self.shell - if self.pylab: - enable = lambda key: shell.enable_pylab(key, import_all=self.pylab_import_all) - key = self.pylab - elif self.matplotlib: - enable = shell.enable_matplotlib - key = self.matplotlib - elif self.gui: - enable = shell.enable_gui - key = self.gui - - if not enable: - return - - try: - r = enable(key) - except ImportError: - self.log.warning("Eventloop or matplotlib integration failed. Is matplotlib installed?") - self.shell.showtraceback() - return - except Exception: - 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, " - "eventloop=%s, matplotlib=%s", gui, backend) - if key == "auto": - print("Using matplotlib backend: %s" % backend) - else: - gui = r - self.log.info("Enabling GUI event loop integration, " - "eventloop=%s", gui) - - def init_extensions(self): - """Load all IPython extensions in IPythonApp.extensions. - - This uses the :meth:`ExtensionManager.load_extensions` to load all - the extensions listed in ``self.extensions``. - """ - try: - self.log.debug("Loading IPython extensions...") - extensions = ( - self.default_extensions + self.extensions + self.extra_extensions - ) - for ext in extensions: - try: - self.log.info("Loading IPython extension: %s" % ext) - self.shell.extension_manager.load_extension(ext) - except: - if self.reraise_ipython_extension_failures: - raise - msg = ("Error in loading extension: {ext}\n" - "Check your config files in {location}".format( - ext=ext, - location=self.profile_dir.location - )) - self.log.warning(msg, exc_info=True) - except: - if self.reraise_ipython_extension_failures: - raise - self.log.warning("Unknown error in loading extensions:", exc_info=True) - - def init_code(self): - """run the pre-flight code, specified via exec_lines""" - 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() - self.shell._sys_modules_keys = set(sys.modules.keys()) - - def _run_exec_lines(self): - """Run lines of code in IPythonApp.exec_lines in the user's namespace.""" - if not self.exec_lines: - return - try: - self.log.debug("Running code from IPythonApp.exec_lines...") - for line in self.exec_lines: - try: - self.log.info("Running code in user namespace: %s" % - line) - self.shell.run_cell(line, store_history=False) - except: - self.log.warning("Error in executing line in user " - "namespace: %s" % line) - self.shell.showtraceback() - except: - self.log.warning("Unknown error in handling IPythonApp.exec_lines:") - self.shell.showtraceback() - - def _exec_file(self, fname, shell_futures=False): - try: - full_filename = filefind(fname, [u'.', self.ipython_dir]) - 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 - # were run from a system shell. - save_argv = sys.argv - sys.argv = [full_filename] + self.extra_args[1:] - try: - if os.path.isfile(full_filename): - self.log.info("Running file in user namespace: %s" % - full_filename) - # Ensure that __file__ is always defined to match Python - # behavior. - with preserve_keys(self.shell.user_ns, '__file__'): - self.shell.user_ns['__file__'] = fname - if full_filename.endswith('.ipy') or full_filename.endswith('.ipynb'): - self.shell.safe_execfile_ipy(full_filename, - shell_futures=shell_futures) - else: - # default to python, even without extension - self.shell.safe_execfile(full_filename, - self.shell.user_ns, - shell_futures=shell_futures, - raise_exceptions=True) - finally: - sys.argv = save_argv - - def _run_startup_files(self): - """Run files from profile startup directory""" - startup_dirs = [self.profile_dir.startup_dir] + [ - 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'] - self.log.debug("Running PYTHONSTARTUP file %s...", python_startup) - try: - self._exec_file(python_startup) - except: - self.log.warning("Unknown error in handling PYTHONSTARTUP file %s:", python_startup) - self.shell.showtraceback() - for startup_dir in startup_dirs[::-1]: - startup_files += glob.glob(os.path.join(startup_dir, '*.py')) - 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): - self._exec_file(fname) - except: - self.log.warning("Unknown error in handling startup files:") - self.shell.showtraceback() - - def _run_exec_files(self): - """Run files from IPythonApp.exec_files""" - if not self.exec_files: - return - - self.log.debug("Running files in IPythonApp.exec_files...") - try: - for fname in self.exec_files: - self._exec_file(fname) - except: - self.log.warning("Unknown error in handling IPythonApp.exec_files:") - self.shell.showtraceback() - - def _run_cmd_line_code(self): - """Run code or file specified at the command-line""" - if self.code_to_run: - line = self.code_to_run - try: - self.log.info("Running code given at command line (c=): %s" % - line) - self.shell.run_cell(line, store_history=False) - except: - self.log.warning("Error in executing line in user namespace: %s" % - line) - self.shell.showtraceback() - 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 not os.path.exists(fname): - self.log.warning("File '%s' doesn't exist", fname) - if not self.interact: - self.exit(2) - try: - self._exec_file(fname, shell_futures=True) - except: - self.shell.showtraceback(tb_offset=4) - if not self.interact: - self.exit(1) - - def _run_module(self): - """Run module specified at the command-line.""" - if self.module_to_run: - # Make sure that the module gets a proper sys.argv as if it were - # run using `python -m`. - save_argv = sys.argv - sys.argv = [sys.executable] + self.extra_args - try: - self.shell.safe_run_module(self.module_to_run, - self.shell.user_ns) - finally: - sys.argv = save_argv diff --git a/contrib/python/ipython/py3/IPython/core/splitinput.py b/contrib/python/ipython/py3/IPython/core/splitinput.py deleted file mode 100644 index 63cdce7955..0000000000 --- a/contrib/python/ipython/py3/IPython/core/splitinput.py +++ /dev/null @@ -1,137 +0,0 @@ -# encoding: utf-8 -""" -Simple utility for splitting user input. This is used by both inputsplitter and -prefilter. - -Authors: - -* Brian Granger -* Fernando Perez -""" - -#----------------------------------------------------------------------------- -# Copyright (C) 2008-2011 The IPython Development Team -# -# Distributed under the terms of the BSD License. The full license is in -# the file COPYING, distributed as part of this software. -#----------------------------------------------------------------------------- - -#----------------------------------------------------------------------------- -# Imports -#----------------------------------------------------------------------------- - -import re -import sys - -from IPython.utils import py3compat -from IPython.utils.encoding import get_stream_enc - -#----------------------------------------------------------------------------- -# Main function -#----------------------------------------------------------------------------- - -# RegExp for splitting line contents into pre-char//first word-method//rest. -# For clarity, each group in on one line. - -# WARNING: update the regexp if the escapes in interactiveshell are changed, as -# they are hardwired in. - -# Although it's not solely driven by the regex, note that: -# ,;/% only trigger if they are the first character on the line -# ! and !! trigger if they are first char(s) *or* follow an indent -# ? triggers as first or last char. - -line_split = re.compile(r""" - ^(\s*) # any leading space - ([,;/%]|!!?|\?\??)? # escape character or characters - \s*(%{0,2}[\w\.\*]*) # function/method, possibly with leading % - # to correctly treat things like '?%magic' - (.*?$|$) # rest of line - """, re.VERBOSE) - - -def split_user_input(line, pattern=None): - """Split user input into initial whitespace, escape character, function part - and the rest. - """ - # We need to ensure that the rest of this routine deals only with unicode - encoding = get_stream_enc(sys.stdin, 'utf-8') - line = py3compat.cast_unicode(line, encoding) - - if pattern is None: - pattern = line_split - match = pattern.match(line) - if not match: - # print "match failed for line '%s'" % line - try: - ifun, the_rest = line.split(None,1) - except ValueError: - # print "split failed for line '%s'" % line - ifun, the_rest = line, u'' - pre = re.match(r'^(\s*)(.*)',line).groups()[0] - esc = "" - else: - pre, esc, ifun, the_rest = match.groups() - - #print 'line:<%s>' % line # dbg - #print 'pre <%s> ifun <%s> rest <%s>' % (pre,ifun.strip(),the_rest) # dbg - return pre, esc or '', ifun.strip(), the_rest.lstrip() - - -class LineInfo(object): - """A single line of input and associated info. - - Includes the following as properties: - - line - The original, raw line - - continue_prompt - Is this line a continuation in a sequence of multiline input? - - pre - Any leading whitespace. - - esc - The escape character(s) in pre or the empty string if there isn't one. - Note that '!!' and '??' are possible values for esc. Otherwise it will - always be a single character. - - ifun - The 'function part', which is basically the maximal initial sequence - of valid python identifiers and the '.' character. This is what is - checked for alias and magic transformations, used for auto-calling, - etc. In contrast to Python identifiers, it may start with "%" and contain - "*". - - the_rest - Everything else on the line. - """ - def __init__(self, line, continue_prompt=False): - self.line = line - self.continue_prompt = continue_prompt - self.pre, self.esc, self.ifun, self.the_rest = split_user_input(line) - - self.pre_char = self.pre.strip() - if self.pre_char: - self.pre_whitespace = '' # No whitespace allowed before esc chars - else: - self.pre_whitespace = self.pre - - def ofind(self, ip): - """Do a full, attribute-walking lookup of the ifun in the various - namespaces for the given IPython InteractiveShell instance. - - Return a dict with keys: {found, obj, ospace, ismagic} - - Note: can cause state changes because of calling getattr, but should - only be run if autocall is on and if the line hasn't matched any - other, less dangerous handlers. - - Does cache the results of the call, so can be called multiple times - without worrying about *further* damaging state. - """ - return ip._ofind(self.ifun) - - def __str__(self): - return "LineInfo [%s|%s|%s|%s]" %(self.pre, self.esc, self.ifun, self.the_rest) diff --git a/contrib/python/ipython/py3/IPython/core/ultratb.py b/contrib/python/ipython/py3/IPython/core/ultratb.py deleted file mode 100644 index 4447080f35..0000000000 --- a/contrib/python/ipython/py3/IPython/core/ultratb.py +++ /dev/null @@ -1,1207 +0,0 @@ -# -*- coding: utf-8 -*- -""" -Verbose and colourful traceback formatting. - -**ColorTB** - -I've always found it a bit hard to visually parse tracebacks in Python. The -ColorTB class is a solution to that problem. It colors the different parts of a -traceback in a manner similar to what you would expect from a syntax-highlighting -text editor. - -Installation instructions for ColorTB:: - - import sys,ultratb - sys.excepthook = ultratb.ColorTB() - -**VerboseTB** - -I've also included a port of Ka-Ping Yee's "cgitb.py" that produces all kinds -of useful info when a traceback occurs. Ping originally had it spit out HTML -and intended it for CGI programmers, but why should they have all the fun? I -altered it to spit out colored text to the terminal. It's a bit overwhelming, -but kind of neat, and maybe useful for long-running programs that you believe -are bug-free. If a crash *does* occur in that type of program you want details. -Give it a shot--you'll love it or you'll hate it. - -.. note:: - - The Verbose mode prints the variables currently visible where the exception - happened (shortening their strings if too long). This can potentially be - very slow, if you happen to have a huge data structure whose string - representation is complex to compute. Your computer may appear to freeze for - a while with cpu usage at 100%. If this occurs, you can cancel the traceback - with Ctrl-C (maybe hitting it more than once). - - If you encounter this kind of situation often, you may want to use the - Verbose_novars mode instead of the regular Verbose, which avoids formatting - 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 unencrypted - password. - -Installation instructions for VerboseTB:: - - import sys,ultratb - sys.excepthook = ultratb.VerboseTB() - -Note: Much of the code in this module was lifted verbatim from the standard -library module 'traceback.py' and Ka-Ping Yee's 'cgitb.py'. - -Color schemes -------------- - -The colors are defined in the class TBTools through the use of the -ColorSchemeTable class. Currently the following exist: - - - NoColor: allows all of this module to be used in any terminal (the color - escapes are just dummy blank strings). - - - Linux: is meant to look good in a terminal like the Linux console (black - or very dark background). - - - 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 - -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. - -Inheritance diagram: - -.. inheritance-diagram:: IPython.core.ultratb - :parts: 3 -""" - -#***************************************************************************** -# Copyright (C) 2001 Nathaniel Gray <n8gray@caltech.edu> -# Copyright (C) 2001-2004 Fernando Perez <fperez@colorado.edu> -# -# Distributed under the terms of the BSD License. The full license is in -# the file COPYING, distributed as part of this software. -#***************************************************************************** - - -import inspect -import linecache -import pydoc -import sys -import time -import traceback -from types import TracebackType -from typing import Tuple, List, Any, Optional - -import stack_data -from pygments.formatters.terminal256 import Terminal256Formatter -from pygments.styles import get_style_by_name - -# IPython's own modules -from IPython import get_ipython -from IPython.core import debugger -from IPython.core.display_trap import DisplayTrap -from IPython.core.excolors import exception_colors -from IPython.utils import path as util_path -from IPython.utils import py3compat -from IPython.utils.terminal import get_terminal_size - -import IPython.utils.colorable as colorable - -# Globals -# amount of space to put line numbers before verbose tracebacks -INDENT_SIZE = 8 - -# Default color scheme. This is used, for example, by the traceback -# formatter. When running in an actual IPython instance, the user's rc.colors -# value is used, but having a module global makes this functionality available -# to users of ultratb who are NOT running inside ipython. -DEFAULT_SCHEME = 'NoColor' - -# --------------------------------------------------------------------------- -# Code begins - -# Helper function -- largely belongs to VerboseTB, but we need the same -# functionality to produce a pseudo verbose TB for SyntaxErrors, so that they -# can be recognized properly by ipython.el's py-traceback-line-re -# (SyntaxErrors have to be treated specially because they have no traceback) - - -def _format_traceback_lines(lines, Colors, has_colors: bool, lvals): - """ - Format tracebacks lines with pointing arrow, leading numbers... - - Parameters - ---------- - lines : list[Line] - Colors - ColorScheme used. - lvals : str - Values of local variables, already colored, to inject just after the error line. - """ - numbers_width = INDENT_SIZE - 1 - res = [] - - for stack_line in lines: - if stack_line is stack_data.LINE_GAP: - res.append('%s (...)%s\n' % (Colors.linenoEm, Colors.Normal)) - continue - - line = stack_line.render(pygmented=has_colors).rstrip('\n') + '\n' - lineno = stack_line.lineno - if stack_line.is_current: - # This is the line with the error - pad = numbers_width - len(str(lineno)) - num = '%s%s' % (debugger.make_arrow(pad), str(lineno)) - start_color = Colors.linenoEm - else: - num = '%*s' % (numbers_width, lineno) - start_color = Colors.lineno - - line = '%s%s%s %s' % (start_color, num, Colors.Normal, line) - - res.append(line) - if lvals and stack_line.is_current: - res.append(lvals + '\n') - return res - - -def _format_filename(file, ColorFilename, ColorNormal, *, lineno=None): - """ - Format filename lines with `In [n]` if it's the nth code cell or `File *.py` if it's a module. - - Parameters - ---------- - file : str - ColorFilename - ColorScheme's filename coloring to be used. - ColorNormal - ColorScheme's normal coloring to be used. - """ - ipinst = get_ipython() - - if ipinst is not None and file in ipinst.compile._filename_map: - file = "[%s]" % ipinst.compile._filename_map[file] - tpl_link = f"Input {ColorFilename}In {{file}}{ColorNormal}" - else: - file = util_path.compress_user( - py3compat.cast_unicode(file, util_path.fs_encoding) - ) - if lineno is None: - tpl_link = f"File {ColorFilename}{{file}}{ColorNormal}" - else: - tpl_link = f"File {ColorFilename}{{file}}:{{lineno}}{ColorNormal}" - - return tpl_link.format(file=file, lineno=lineno) - -#--------------------------------------------------------------------------- -# Module classes -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, - *, - debugger_cls=None, - ): - # Whether to call the interactive pdb debugger after printing - # tracebacks or not - 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 - # 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. - self._ostream = ostream - - # Create color table - self.color_scheme_table = exception_colors() - - self.set_colors(color_scheme) - self.old_scheme = color_scheme # save initial value for toggles - self.debugger_cls = debugger_cls or debugger.Pdb - - if call_pdb: - self.pdb = self.debugger_cls() - else: - self.pdb = None - - def _get_ostream(self): - """Output stream that exceptions are written to. - - Valid values are: - - - None: the default, which means that IPython will dynamically resolve - 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 - - def _set_ostream(self, val): - assert val is None or (hasattr(val, 'write') and hasattr(val, 'flush')) - self._ostream = val - - ostream = property(_get_ostream, _set_ostream) - - @staticmethod - def _get_chained_exception(exception_value): - cause = getattr(exception_value, "__cause__", None) - if cause: - return cause - if getattr(exception_value, "__suppress_context__", False): - return None - return getattr(exception_value, "__context__", None) - - def get_parts_of_chained_exception( - self, evalue - ) -> Optional[Tuple[type, BaseException, TracebackType]]: - - chained_evalue = self._get_chained_exception(evalue) - - if chained_evalue: - return chained_evalue.__class__, chained_evalue, chained_evalue.__traceback__ - return None - - def prepare_chained_exception_message(self, cause) -> List[Any]: - direct_cause = "\nThe above exception was the direct cause of the following exception:\n" - exception_during_handling = "\nDuring handling of the above exception, another exception occurred:\n" - - if cause: - message = [[direct_cause]] - else: - message = [[exception_during_handling]] - return message - - @property - def has_colors(self) -> bool: - return self.color_scheme_table.active_scheme_name.lower() != "nocolor" - - def set_colors(self, *args, **kw): - """Shorthand access to the color table scheme selector method.""" - - # Set own color table - self.color_scheme_table.set_active_scheme(*args, **kw) - # for convenience, set Colors to the active scheme - self.Colors = self.color_scheme_table.active_colors - # Also set colors of debugger - if hasattr(self, 'pdb') and self.pdb is not None: - self.pdb.set_colors(*args, **kw) - - def color_toggle(self): - """Toggle between the currently active color scheme and NoColor.""" - - if self.color_scheme_table.active_scheme_name == 'NoColor': - self.color_scheme_table.set_active_scheme(self.old_scheme) - self.Colors = self.color_scheme_table.active_colors - else: - self.old_scheme = self.color_scheme_table.active_scheme_name - self.color_scheme_table.set_active_scheme('NoColor') - self.Colors = self.color_scheme_table.active_colors - - def stb2text(self, stb): - """Convert a structured traceback (a list) to a string.""" - return '\n'.join(stb) - - def text(self, etype, value, tb, tb_offset: Optional[int] = None, context=5): - """Return formatted traceback. - - Subclasses may override this if they add extra arguments. - """ - tb_list = self.structured_traceback(etype, value, tb, - tb_offset, context) - return self.stb2text(tb_list) - - def structured_traceback( - self, etype, evalue, tb, tb_offset: Optional[int] = None, context=5, mode=None - ): - """Return a list of traceback frames. - - Must be implemented by each class. - """ - raise NotImplementedError() - - -#--------------------------------------------------------------------------- -class ListTB(TBTools): - """Print traceback information from a traceback list, with optional color. - - Calling requires 3 arguments: (etype, evalue, elist) - as would be obtained by:: - - etype, evalue, tb = sys.exc_info() - if tb: - elist = traceback.extract_tb(tb) - else: - elist = None - - It can thus be used by programs which need to process the traceback before - printing (such as console replacements based on the code module from the - standard library). - - 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 __call__(self, etype, value, elist): - self.ostream.flush() - self.ostream.write(self.text(etype, value, elist)) - self.ostream.write('\n') - - def _extract_tb(self, tb): - if tb: - return traceback.extract_tb(tb) - else: - return None - - def structured_traceback( - self, - etype: type, - evalue: BaseException, - etb: Optional[TracebackType] = None, - tb_offset: Optional[int] = None, - context=5, - ): - """Return a color formatted string with the traceback info. - - Parameters - ---------- - etype : exception type - Type of the exception raised. - evalue : object - Data stored in the exception - etb : list | TracebackType | None - If list: List of frames, see class docstring for details. - If Traceback: Traceback of the exception. - tb_offset : int, optional - Number of frames in the traceback to skip. If not given, the - instance evalue is used (set in constructor). - context : int, optional - Number of lines of context information to print. - - Returns - ------- - String with formatted exception. - """ - # This is a workaround to get chained_exc_ids in recursive calls - # etb should not be a tuple if structured_traceback is not recursive - if isinstance(etb, tuple): - etb, chained_exc_ids = etb - else: - chained_exc_ids = set() - - if isinstance(etb, list): - elist = etb - elif etb is not None: - elist = self._extract_tb(etb) - else: - elist = [] - tb_offset = self.tb_offset if tb_offset is None else tb_offset - assert isinstance(tb_offset, int) - Colors = self.Colors - out_list = [] - if elist: - - if tb_offset and len(elist) > tb_offset: - elist = elist[tb_offset:] - - out_list.append('Traceback %s(most recent call last)%s:' % - (Colors.normalEm, Colors.Normal) + '\n') - out_list.extend(self._format_list(elist)) - # The exception info should be a single entry in the list. - lines = ''.join(self._format_exception_only(etype, evalue)) - out_list.append(lines) - - exception = self.get_parts_of_chained_exception(evalue) - - if exception and not id(exception[1]) in chained_exc_ids: - chained_exception_message = self.prepare_chained_exception_message( - evalue.__cause__)[0] - etype, evalue, etb = exception - # Trace exception to avoid infinite 'cause' loop - chained_exc_ids.add(id(exception[1])) - chained_exceptions_tb_offset = 0 - out_list = ( - self.structured_traceback( - etype, evalue, (etb, chained_exc_ids), - chained_exceptions_tb_offset, context) - + chained_exception_message - + out_list) - - return out_list - - def _format_list(self, extracted_list): - """Format a list of traceback entry tuples for printing. - - Given a list of tuples as returned by extract_tb() or - extract_stack(), return a list of strings ready for printing. - Each string in the resulting list corresponds to the item with the - same index in the argument list. Each string ends in a newline; - the strings may contain internal newlines as well, for those items - whose source text line is not None. - - Lifted almost verbatim from traceback.py - """ - - Colors = self.Colors - list = [] - for filename, lineno, name, line in extracted_list[:-1]: - item = " %s in %s%s%s\n" % ( - _format_filename( - filename, Colors.filename, Colors.Normal, lineno=lineno - ), - Colors.name, - name, - Colors.Normal, - ) - if line: - item += ' %s\n' % line.strip() - list.append(item) - # Emphasize the last entry - filename, lineno, name, line = extracted_list[-1] - item = "%s %s in %s%s%s%s\n" % ( - Colors.normalEm, - _format_filename( - filename, Colors.filenameEm, Colors.normalEm, lineno=lineno - ), - Colors.nameEm, - name, - Colors.normalEm, - Colors.Normal, - ) - if line: - item += '%s %s%s\n' % (Colors.line, line.strip(), - Colors.Normal) - list.append(item) - return list - - def _format_exception_only(self, etype, value): - """Format the exception part of a traceback. - - The arguments are the exception type and value such as given by - sys.exc_info()[:2]. The return value is a list of strings, each ending - in a newline. Normally, the list contains a single string; however, - for SyntaxError exceptions, it contains several lines that (when - printed) display detailed information about where the syntax error - occurred. The message indicating which exception occurred is the - always last string in the list. - - Also lifted nearly verbatim from traceback.py - """ - have_filedata = False - Colors = self.Colors - list = [] - 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') - else: - if issubclass(etype, SyntaxError): - have_filedata = True - if not value.filename: value.filename = "<string>" - if value.lineno: - lineno = value.lineno - textline = linecache.getline(value.filename, value.lineno) - else: - lineno = "unknown" - textline = "" - list.append( - "%s %s%s\n" - % ( - Colors.normalEm, - _format_filename( - value.filename, - Colors.filenameEm, - Colors.normalEm, - lineno=(None if lineno == "unknown" else lineno), - ), - Colors.Normal, - ) - ) - if textline == "": - textline = py3compat.cast_unicode(value.text, "utf-8") - - if textline is not None: - i = 0 - while i < len(textline) and textline[i].isspace(): - i += 1 - list.append('%s %s%s\n' % (Colors.line, - textline.strip(), - Colors.Normal)) - if value.offset is not None: - s = ' ' - for c in textline[i:value.offset - 1]: - if c.isspace(): - s += c - else: - s += ' ' - list.append('%s%s^%s\n' % (Colors.caret, s, - Colors.Normal)) - - try: - s = value.msg - except Exception: - s = self._some_str(value) - if s: - list.append('%s%s:%s %s\n' % (stype, Colors.excName, - Colors.Normal, s)) - else: - list.append('%s\n' % stype) - - # sync with user hooks - if have_filedata: - ipinst = get_ipython() - if ipinst is not None: - ipinst.hooks.synchronize_with_editor(value.filename, value.lineno, 0) - - return list - - def get_exception_only(self, etype, value): - """Only print the exception type and message, without a traceback. - - Parameters - ---------- - etype : exception type - value : exception value - """ - return ListTB.structured_traceback(self, etype, value) - - def show_exception_only(self, etype, evalue): - """Only print the exception type and message, without a traceback. - - Parameters - ---------- - etype : exception type - evalue : exception value - """ - # This method needs to use __call__ from *this* class, not the one from - # a subclass whose signature or behavior may be different - ostream = self.ostream - ostream.flush() - ostream.write('\n'.join(self.get_exception_only(etype, evalue))) - ostream.flush() - - def _some_str(self, value): - # Lifted from traceback.py - try: - return py3compat.cast_unicode(str(value)) - except: - return u'<unprintable %s object>' % type(value).__name__ - - -#---------------------------------------------------------------------------- -class VerboseTB(TBTools): - """A port of Ka-Ping Yee's cgitb.py module that outputs color text instead - of HTML. Requires inspect and pydoc. Crazy, man. - - Modified version which optionally strips the topmost entries from the - traceback, to be used with alternate interpreters (because their own code - would appear in the traceback).""" - - def __init__( - self, - color_scheme: str = "Linux", - call_pdb: bool = False, - ostream=None, - tb_offset: int = 0, - long_header: bool = False, - include_vars: bool = True, - check_cache=None, - debugger_cls=None, - parent=None, - config=None, - ): - """Specify traceback offset, headers and color scheme. - - Define how many frames to drop from the tracebacks. Calling it with - tb_offset=1 allows use of this handler in interpreters which will have - their own code at the top of the traceback (VerboseTB will first - remove that frame before printing the traceback info).""" - TBTools.__init__( - self, - color_scheme=color_scheme, - call_pdb=call_pdb, - ostream=ostream, - parent=parent, - config=config, - debugger_cls=debugger_cls, - ) - self.tb_offset = tb_offset - self.long_header = long_header - self.include_vars = include_vars - # By default we use linecache.checkcache, but the user can provide a - # different check_cache implementation. This is used by the IPython - # kernel to provide tracebacks for interactive code that is cached, - # by a compiler instance that flushes the linecache but preserves its - # own code cache. - if check_cache is None: - check_cache = linecache.checkcache - self.check_cache = check_cache - - self.skip_hidden = True - - def format_record(self, frame_info): - """Format a single stack frame""" - Colors = self.Colors # just a shorthand + quicker name lookup - ColorsNormal = Colors.Normal # used a lot - - if isinstance(frame_info, stack_data.RepeatedFrames): - return ' %s[... skipping similar frames: %s]%s\n' % ( - Colors.excName, frame_info.description, ColorsNormal) - - indent = " " * INDENT_SIZE - em_normal = "%s\n%s%s" % (Colors.valEm, indent, ColorsNormal) - tpl_call = f"in {Colors.vName}{{file}}{Colors.valEm}{{scope}}{ColorsNormal}" - tpl_call_fail = "in %s%%s%s(***failed resolving arguments***)%s" % ( - Colors.vName, - Colors.valEm, - ColorsNormal, - ) - tpl_name_val = "%%s %s= %%s%s" % (Colors.valEm, ColorsNormal) - - link = _format_filename( - frame_info.filename, - Colors.filenameEm, - ColorsNormal, - lineno=frame_info.lineno, - ) - args, varargs, varkw, locals_ = inspect.getargvalues(frame_info.frame) - - func = frame_info.executing.code_qualname() - if func == "<module>": - call = tpl_call.format(file=func, scope="") - else: - # Decide whether to include variable details or not - var_repr = eqrepr if self.include_vars else nullrepr - try: - scope = inspect.formatargvalues( - args, varargs, varkw, locals_, formatvalue=var_repr - ) - call = tpl_call.format(file=func, scope=scope) - except KeyError: - # This happens in situations like errors inside generator - # expressions, where local variables are listed in the - # line, but can't be extracted from the frame. I'm not - # 100% sure this isn't actually a bug in inspect itself, - # but since there's no info for us to compute with, the - # best we can do is report the failure and move on. Here - # we must *not* call any traceback construction again, - # because that would mess up use of %debug later on. So we - # simply report the failure and move on. The only - # limitation will be that this frame won't have locals - # listed in the call signature. Quite subtle problem... - # I can't think of a good way to validate this in a unit - # test, but running a script consisting of: - # dict( (k,v.strip()) for (k,v) in range(10) ) - # will illustrate the error, if this exception catch is - # disabled. - call = tpl_call_fail % func - - lvals = '' - lvals_list = [] - if self.include_vars: - try: - # we likely want to fix stackdata at some point, but - # still need a workaround. - fibp = frame_info.variables_in_executing_piece - for var in fibp: - lvals_list.append(tpl_name_val % (var.name, repr(var.value))) - except Exception: - lvals_list.append( - "Exception trying to inspect frame. No more locals available." - ) - if lvals_list: - lvals = '%s%s' % (indent, em_normal.join(lvals_list)) - - result = "%s, %s\n" % (link, call) - - result += ''.join(_format_traceback_lines(frame_info.lines, Colors, self.has_colors, lvals)) - return result - - def prepare_header(self, etype, long_version=False): - 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]) - 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 += "\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))) ) - - return head - - def format_exception(self, etype, evalue): - colors = self.Colors # just a shorthand + quicker name lookup - colorsnormal = colors.Normal # used a lot - # Get (safely) a string form of the exception info - try: - etype_str, evalue_str = map(str, (etype, evalue)) - except: - # User exception is improperly defined. - etype, evalue = str, sys.exc_info()[:2] - etype_str, evalue_str = map(str, (etype, evalue)) - # ... and format it - return ['%s%s%s: %s' % (colors.excName, etype_str, - colorsnormal, py3compat.cast_unicode(evalue_str))] - - def format_exception_as_a_whole( - self, - etype: type, - evalue: BaseException, - etb: Optional[TracebackType], - number_of_lines_of_context, - tb_offset: Optional[int], - ): - """Formats the header, traceback and exception message for a single exception. - - This may be called multiple times by Python 3 exception chaining - (PEP 3134). - """ - # some locals - orig_etype = etype - try: - etype = etype.__name__ - except AttributeError: - pass - - tb_offset = self.tb_offset if tb_offset is None else tb_offset - assert isinstance(tb_offset, int) - head = self.prepare_header(etype, self.long_header) - records = ( - self.get_records(etb, number_of_lines_of_context, tb_offset) if etb else [] - ) - - frames = [] - skipped = 0 - lastrecord = len(records) - 1 - for i, r in enumerate(records): - if not isinstance(r, stack_data.RepeatedFrames) and self.skip_hidden: - if r.frame.f_locals.get("__tracebackhide__", 0) and i != lastrecord: - skipped += 1 - continue - if skipped: - Colors = self.Colors # just a shorthand + quicker name lookup - ColorsNormal = Colors.Normal # used a lot - frames.append( - " %s[... skipping hidden %s frame]%s\n" - % (Colors.excName, skipped, ColorsNormal) - ) - skipped = 0 - frames.append(self.format_record(r)) - if skipped: - Colors = self.Colors # just a shorthand + quicker name lookup - ColorsNormal = Colors.Normal # used a lot - frames.append( - " %s[... skipping hidden %s frame]%s\n" - % (Colors.excName, skipped, ColorsNormal) - ) - - formatted_exception = self.format_exception(etype, evalue) - if records: - frame_info = records[-1] - ipinst = get_ipython() - if ipinst is not None: - ipinst.hooks.synchronize_with_editor(frame_info.filename, frame_info.lineno, 0) - - return [[head] + frames + [''.join(formatted_exception[0])]] - - def get_records( - self, etb: TracebackType, number_of_lines_of_context: int, tb_offset: int - ): - assert etb is not None - context = number_of_lines_of_context - 1 - after = context // 2 - before = context - after - if self.has_colors: - style = get_style_by_name("default") - style = stack_data.style_with_executing_node(style, "") - formatter = Terminal256Formatter(style=style) - else: - formatter = None - options = stack_data.Options( - before=before, - after=after, - pygments_formatter=formatter, - ) - return list(stack_data.FrameInfo.stack_data(etb, options=options))[tb_offset:] - - def structured_traceback( - self, - etype: type, - evalue: Optional[BaseException], - etb: Optional[TracebackType], - tb_offset: Optional[int] = None, - number_of_lines_of_context: int = 5, - ): - """Return a nice text document describing the traceback.""" - formatted_exception = self.format_exception_as_a_whole(etype, evalue, etb, number_of_lines_of_context, - tb_offset) - - 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) - structured_traceback_parts = [head] - chained_exceptions_tb_offset = 0 - lines_of_context = 3 - formatted_exceptions = formatted_exception - exception = self.get_parts_of_chained_exception(evalue) - if exception: - assert evalue is not None - formatted_exceptions += self.prepare_chained_exception_message(evalue.__cause__) - etype, evalue, etb = exception - else: - evalue = None - chained_exc_ids = set() - while evalue: - formatted_exceptions += self.format_exception_as_a_whole(etype, evalue, etb, lines_of_context, - chained_exceptions_tb_offset) - exception = self.get_parts_of_chained_exception(evalue) - - if exception and not id(exception[1]) in chained_exc_ids: - chained_exc_ids.add(id(exception[1])) # trace exception to avoid infinite 'cause' loop - formatted_exceptions += self.prepare_chained_exception_message(evalue.__cause__) - etype, evalue, etb = exception - else: - evalue = None - - # we want to see exceptions in a reversed order: - # the first exception should be on top - for formatted_exception in reversed(formatted_exceptions): - structured_traceback_parts += formatted_exception - - return structured_traceback_parts - - def debugger(self, force: bool = False): - """Call up the pdb debugger if desired, always clean up the tb - reference. - - Keywords: - - - force(False): by default, this routine checks the instance call_pdb - flag and does not actually invoke the debugger if the flag is false. - The 'force' option forces the debugger to activate even if the flag - is false. - - If the call_pdb flag is set, the pdb interactive debugger is - invoked. In all cases, the self.tb reference to the current traceback - is deleted to prevent lingering references which hamper memory - management. - - Note that each call to pdb() does an 'import readline', so if your app - requires a special setup for the readline completers, you'll have to - fix that by hand after invoking the exception handler.""" - - if force or self.call_pdb: - if self.pdb is None: - self.pdb = self.debugger_cls() - # the system displayhook may have changed, restore the original - # for pdb - display_trap = DisplayTrap(hook=sys.__displayhook__) - with display_trap: - self.pdb.reset() - # Find the right frame so we don't pop up inside ipython itself - if hasattr(self, 'tb') and self.tb is not None: - etb = self.tb - else: - etb = self.tb = sys.last_traceback - while self.tb is not None and self.tb.tb_next is not None: - assert self.tb.tb_next is not None - self.tb = self.tb.tb_next - if etb and etb.tb_next: - etb = etb.tb_next - self.pdb.botframe = etb.tb_frame - self.pdb.interaction(None, etb) - - if hasattr(self, 'tb'): - del self.tb - - def handler(self, info=None): - (etype, evalue, etb) = info or sys.exc_info() - self.tb = etb - ostream = self.ostream - ostream.flush() - ostream.write(self.text(etype, evalue, etb)) - ostream.write('\n') - ostream.flush() - - # Changed so an instance can just be called as VerboseTB_inst() and print - # out the right info on its own. - def __call__(self, etype=None, evalue=None, etb=None): - """This hook can replace sys.excepthook (for Python 2.1 or higher).""" - if etb is None: - self.handler() - else: - self.handler((etype, evalue, etb)) - try: - self.debugger() - except KeyboardInterrupt: - print("\nKeyboardInterrupt") - - -#---------------------------------------------------------------------------- -class FormattedTB(VerboseTB, ListTB): - """Subclass ListTB but allow calling with a traceback. - - It can thus be used as a sys.excepthook for Python > 2.1. - - Also adds 'Context' and 'Verbose' modes, not available in ListTB. - - Allows a tb_offset to be specified. This is useful for situations where - one needs to remove a number of topmost frames from the traceback (such as - occurs with python programs that themselves execute other python code, - like Python shells). """ - - mode: str - - 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, - parent=None, config=None): - - # NEVER change the order of this list. Put new modes at the end: - self.valid_modes = ['Plain', 'Context', 'Verbose', 'Minimal'] - self.verbose_modes = self.valid_modes[1:3] - - 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, - parent=parent, config=config) - - # Different types of tracebacks are joined with different separators to - # form a single string. They are taken from this dict - self._join_chars = dict(Plain='', Context='\n', Verbose='\n', - Minimal='') - # set_mode also sets the tb_join_char attribute - self.set_mode(mode) - - def structured_traceback(self, etype, value, tb, tb_offset=None, number_of_lines_of_context=5): - tb_offset = self.tb_offset if tb_offset is None else tb_offset - mode = self.mode - if mode in self.verbose_modes: - # Verbose modes need a full traceback - return VerboseTB.structured_traceback( - self, etype, value, tb, tb_offset, number_of_lines_of_context - ) - elif mode == 'Minimal': - return ListTB.get_exception_only(self, etype, value) - else: - # We must check the source cache because otherwise we can print - # out-of-date source code. - self.check_cache() - # Now we can extract and format the exception - return ListTB.structured_traceback( - self, etype, value, tb, tb_offset, number_of_lines_of_context - ) - - def stb2text(self, stb): - """Convert a structured traceback (a list) to a string.""" - return self.tb_join_char.join(stb) - - def set_mode(self, mode: Optional[str] = None): - """Switch to the desired mode. - - If mode is not specified, cycles through the available modes.""" - - if not mode: - new_idx = (self.valid_modes.index(self.mode) + 1 ) % \ - len(self.valid_modes) - self.mode = self.valid_modes[new_idx] - elif mode not in self.valid_modes: - raise ValueError( - "Unrecognized mode in FormattedTB: <" + mode + ">\n" - "Valid modes: " + str(self.valid_modes) - ) - else: - assert isinstance(mode, str) - self.mode = mode - # include variable details only in 'Verbose' mode - self.include_vars = (self.mode == self.valid_modes[2]) - # Set the join character for generating text tracebacks - self.tb_join_char = self._join_chars[self.mode] - - # some convenient shortcuts - def plain(self): - self.set_mode(self.valid_modes[0]) - - def context(self): - self.set_mode(self.valid_modes[1]) - - def verbose(self): - self.set_mode(self.valid_modes[2]) - - def minimal(self): - self.set_mode(self.valid_modes[3]) - - -#---------------------------------------------------------------------------- -class AutoFormattedTB(FormattedTB): - """A traceback printer which can be called on the fly. - - It will find out about exceptions by itself. - - A brief example:: - - AutoTB = AutoFormattedTB(mode = 'Verbose',color_scheme='Linux') - try: - ... - except: - AutoTB() # or AutoTB(out=logfile) where logfile is an open file object - """ - - def __call__(self, etype=None, evalue=None, etb=None, - out=None, tb_offset=None): - """Print out a formatted exception traceback. - - Optional arguments: - - out: an open file-like object to direct output to. - - - tb_offset: the number of frames to skip over in the stack, on a - per-call basis (this overrides temporarily the instance's tb_offset - given at initialization time.""" - - if out is None: - out = self.ostream - out.flush() - out.write(self.text(etype, evalue, etb, tb_offset)) - out.write('\n') - out.flush() - # FIXME: we should remove the auto pdb behavior from here and leave - # that to the clients. - try: - self.debugger() - except KeyboardInterrupt: - print("\nKeyboardInterrupt") - - def structured_traceback(self, etype=None, value=None, tb=None, - tb_offset=None, number_of_lines_of_context=5): - - etype: type - value: BaseException - # tb: TracebackType or tupleof tb types ? - if etype is None: - etype, value, tb = sys.exc_info() - if isinstance(tb, tuple): - # tb is a tuple if this is a chained exception. - self.tb = tb[0] - else: - self.tb = tb - return FormattedTB.structured_traceback( - self, etype, value, tb, tb_offset, number_of_lines_of_context) - - -#--------------------------------------------------------------------------- - -# A simple class to preserve Nathan's original functionality. -class ColorTB(FormattedTB): - """Shorthand to initialize a FormattedTB in Linux colors mode.""" - - def __init__(self, color_scheme='Linux', call_pdb=0, **kwargs): - FormattedTB.__init__(self, color_scheme=color_scheme, - call_pdb=call_pdb, **kwargs) - - -class SyntaxTB(ListTB): - """Extension which holds some state: the last exception value""" - - def __init__(self, color_scheme='NoColor', parent=None, config=None): - ListTB.__init__(self, color_scheme, parent=parent, config=config) - self.last_syntax_error = None - - def __call__(self, etype, value, elist): - self.last_syntax_error = value - - ListTB.__call__(self, etype, value, elist) - - def structured_traceback(self, etype, value, elist, tb_offset=None, - context=5): - # If the source file has been edited, the line in the syntax error can - # be wrong (retrieved from an outdated cache). This replaces it with - # the current value. - if isinstance(value, SyntaxError) \ - and isinstance(value.filename, str) \ - and isinstance(value.lineno, int): - linecache.checkcache(value.filename) - newtext = linecache.getline(value.filename, value.lineno) - if newtext: - value.text = newtext - self.last_syntax_error = value - return super(SyntaxTB, self).structured_traceback(etype, value, elist, - tb_offset=tb_offset, context=context) - - def clear_err_state(self): - """Return the current error state and clear it""" - e = self.last_syntax_error - self.last_syntax_error = None - return e - - def stb2text(self, stb): - """Convert a structured traceback (a list) to a string.""" - return ''.join(stb) - - -# some internal-use functions -def text_repr(value): - """Hopefully pretty robust repr equivalent.""" - # this is pretty horrible but should always return *something* - try: - return pydoc.text.repr(value) - except KeyboardInterrupt: - raise - except: - try: - return repr(value) - except KeyboardInterrupt: - raise - except: - try: - # all still in an except block so we catch - # getattr raising - name = getattr(value, '__name__', None) - if name: - # ick, recursion - return text_repr(name) - klass = getattr(value, '__class__', None) - if klass: - return '%s instance' % text_repr(klass) - except KeyboardInterrupt: - raise - except: - return 'UNRECOVERABLE REPR FAILURE' - - -def eqrepr(value, repr=text_repr): - return '=%s' % repr(value) - - -def nullrepr(value, repr=text_repr): - return '' diff --git a/contrib/python/ipython/py3/IPython/core/usage.py b/contrib/python/ipython/py3/IPython/core/usage.py deleted file mode 100644 index 53219bceb2..0000000000 --- a/contrib/python/ipython/py3/IPython/core/usage.py +++ /dev/null @@ -1,341 +0,0 @@ -# -*- coding: utf-8 -*- -"""Usage information for the main IPython applications. -""" -#----------------------------------------------------------------------------- -# Copyright (C) 2008-2011 The IPython Development Team -# Copyright (C) 2001-2007 Fernando Perez. <fperez@colorado.edu> -# -# Distributed under the terms of the BSD License. The full license is in -# the file COPYING, distributed as part of this software. -#----------------------------------------------------------------------------- - -import sys -from IPython.core import release - -cl_usage = """\ -========= - IPython -========= - -Tools for Interactive Computing in Python -========================================= - - A Python shell with automatic history (input and output), dynamic object - introspection, easier configuration, command completion, access to the - system shell and more. IPython can also be embedded in running programs. - - -Usage - - ipython [subcommand] [options] [-c cmd | -m mod | file] [--] [arg] ... - - If invoked with no options, it executes the file and exits, passing the - remaining arguments to the script, just as if you had specified the same - command with python. You may need to specify `--` before args to be passed - to the script, to prevent IPython from attempting to parse them. If you - specify the option `-i` before the filename, it will enter an interactive - IPython session after running the script, rather than exiting. Files ending - in .py will be treated as normal Python, but files ending in .ipy can - contain special IPython syntax (magic commands, shell expansions, etc.). - - Almost all configuration in IPython is available via the command-line. Do - `ipython --help-all` to see all available options. For persistent - configuration, look into your `ipython_config.py` configuration file for - details. - - This file is typically installed in the `IPYTHONDIR` directory, and there - is a separate configuration directory for each profile. The default profile - directory will be located in $IPYTHONDIR/profile_default. IPYTHONDIR - defaults to to `$HOME/.ipython`. For Windows users, $HOME resolves to - C:\\Users\\YourUserName in most instances. - - To initialize a profile with the default configuration file, do:: - - $> ipython profile create - - and start editing `IPYTHONDIR/profile_default/ipython_config.py` - - In IPython's documentation, we will refer to this directory as - `IPYTHONDIR`, you can change its default location by creating an - environment variable with this name and setting it to the desired path. - - For more information, see the manual available in HTML and PDF in your - installation, or online at https://ipython.org/documentation.html. -""" - -interactive_usage = """ -IPython -- An enhanced Interactive Python -========================================= - -IPython offers a fully compatible replacement for the standard Python -interpreter, with convenient shell features, special commands, command -history mechanism and output results caching. - -At your system command line, type 'ipython -h' to see the command line -options available. This document only describes interactive features. - -GETTING HELP ------------- - -Within IPython you have various way to access help: - - ? -> Introduction and overview of IPython's features (this screen). - object? -> Details about 'object'. - object?? -> More detailed, verbose information about 'object'. - %quickref -> Quick reference of all IPython specific syntax and magics. - help -> Access Python's own help system. - -If you are in terminal IPython you can quit this screen by pressing `q`. - - -MAIN FEATURES -------------- - -* Access to the standard Python help with object docstrings and the Python - manuals. Simply type 'help' (no quotes) to invoke it. - -* Magic commands: type %magic for information on the magic subsystem. - -* System command aliases, via the %alias command or the configuration file(s). - -* Dynamic object information: - - Typing ?word or word? prints detailed information about an object. Certain - long strings (code, etc.) get snipped in the center for brevity. - - Typing ??word or word?? gives access to the full information without - snipping long strings. Strings that are longer than the screen are printed - through the less pager. - - The ?/?? system gives access to the full source code for any object (if - available), shows function prototypes and other useful information. - - If you just want to see an object's docstring, type '%pdoc object' (without - quotes, and without % if you have automagic on). - -* Tab completion in the local namespace: - - At any time, hitting tab will complete any available python commands or - variable names, and show you a list of the possible completions if there's - no unambiguous one. It will also complete filenames in the current directory. - -* Search previous command history in multiple ways: - - - Start typing, and then use arrow keys up/down or (Ctrl-p/Ctrl-n) to search - through the history items that match what you've typed so far. - - - Hit Ctrl-r: opens a search prompt. Begin typing and the system searches - your history for lines that match what you've typed so far, completing as - much as it can. - - - %hist: search history by index. - -* Persistent command history across sessions. - -* Logging of input with the ability to save and restore a working session. - -* System shell with !. Typing !ls will run 'ls' in the current directory. - -* The reload command does a 'deep' reload of a module: changes made to the - module since you imported will actually be available without having to exit. - -* Verbose and colored exception traceback printouts. See the magic xmode and - xcolor functions for details (just type %magic). - -* Input caching system: - - IPython offers numbered prompts (In/Out) with input and output caching. All - input is saved and can be retrieved as variables (besides the usual arrow - key recall). - - The following GLOBAL variables always exist (so don't overwrite them!): - _i: stores previous input. - _ii: next previous. - _iii: next-next previous. - _ih : a list of all input _ih[n] is the input from line n. - - Additionally, global variables named _i<n> are dynamically created (<n> - being the prompt counter), such that _i<n> == _ih[<n>] - - For example, what you typed at prompt 14 is available as _i14 and _ih[14]. - - You can create macros which contain multiple input lines from this history, - for later re-execution, with the %macro function. - - The history function %hist allows you to see any part of your input history - by printing a range of the _i variables. Note that inputs which contain - magic functions (%) appear in the history with a prepended comment. This is - because they aren't really valid Python code, so you can't exec them. - -* Output caching system: - - For output that is returned from actions, a system similar to the input - cache exists but using _ instead of _i. Only actions that produce a result - (NOT assignments, for example) are cached. If you are familiar with - Mathematica, IPython's _ variables behave exactly like Mathematica's % - variables. - - The following GLOBAL variables always exist (so don't overwrite them!): - _ (one underscore): previous output. - __ (two underscores): next previous. - ___ (three underscores): next-next previous. - - Global variables named _<n> are dynamically created (<n> being the prompt - counter), such that the result of output <n> is always available as _<n>. - - Finally, a global dictionary named _oh exists with entries for all lines - which generated output. - -* Directory history: - - Your history of visited directories is kept in the global list _dh, and the - magic %cd command can be used to go to any entry in that list. - -* Auto-parentheses and auto-quotes (adapted from Nathan Gray's LazyPython) - - 1. Auto-parentheses - - Callable objects (i.e. functions, methods, etc) can be invoked like - this (notice the commas between the arguments):: - - In [1]: callable_ob arg1, arg2, arg3 - - and the input will be translated to this:: - - callable_ob(arg1, arg2, arg3) - - This feature is off by default (in rare cases it can produce - undesirable side-effects), but you can activate it at the command-line - by starting IPython with `--autocall 1`, set it permanently in your - configuration file, or turn on at runtime with `%autocall 1`. - - You can force auto-parentheses by using '/' as the first character - of a line. For example:: - - In [1]: /globals # becomes 'globals()' - - Note that the '/' MUST be the first character on the line! This - won't work:: - - In [2]: print /globals # syntax error - - In most cases the automatic algorithm should work, so you should - rarely need to explicitly invoke /. One notable exception is if you - are trying to call a function with a list of tuples as arguments (the - parenthesis will confuse IPython):: - - In [1]: zip (1,2,3),(4,5,6) # won't work - - but this will work:: - - In [2]: /zip (1,2,3),(4,5,6) - ------> zip ((1,2,3),(4,5,6)) - Out[2]= [(1, 4), (2, 5), (3, 6)] - - IPython tells you that it has altered your command line by - displaying the new command line preceded by -->. e.g.:: - - In [18]: callable list - -------> callable (list) - - 2. Auto-Quoting - - You can force auto-quoting of a function's arguments by using ',' as - the first character of a line. For example:: - - In [1]: ,my_function /home/me # becomes my_function("/home/me") - - If you use ';' instead, the whole argument is quoted as a single - string (while ',' splits on whitespace):: - - In [2]: ,my_function a b c # becomes my_function("a","b","c") - In [3]: ;my_function a b c # becomes my_function("a b c") - - Note that the ',' MUST be the first character on the line! This - won't work:: - - In [4]: x = ,my_function /home/me # syntax error -""" - -interactive_usage_min = """\ -An enhanced console for Python. -Some of its features are: -- Tab completion in the local namespace. -- Logging of input, see command-line options. -- System shell escape via ! , eg !ls. -- Magic commands, starting with a % (like %ls, %pwd, %cd, etc.) -- Keeps track of locally defined variables via %who, %whos. -- Show object information with a ? eg ?x or x? (use ?? for more info). -""" - -quick_reference = r""" -IPython -- An enhanced Interactive Python - Quick Reference Card -================================================================ - -obj?, obj?? : Get help, or more help for object (also works as - ?obj, ??obj). -?foo.*abc* : List names in 'foo' containing 'abc' in them. -%magic : Information about IPython's 'magic' % functions. - -Magic functions are prefixed by % or %%, and typically take their arguments -without parentheses, quotes or even commas for convenience. Line magics take a -single % and cell magics are prefixed with two %%. - -Example magic function calls: - -%alias d ls -F : 'd' is now an alias for 'ls -F' -alias d ls -F : Works if 'alias' not a python name -alist = %alias : Get list of aliases to 'alist' -cd /usr/share : Obvious. cd -<tab> to choose from visited dirs. -%cd?? : See help AND source for magic %cd -%timeit x=10 : time the 'x=10' statement with high precision. -%%timeit x=2**100 -x**100 : time 'x**100' with a setup of 'x=2**100'; setup code is not - counted. This is an example of a cell magic. - -System commands: - -!cp a.txt b/ : System command escape, calls os.system() -cp a.txt b/ : after %rehashx, most system commands work without ! -cp ${f}.txt $bar : Variable expansion in magics and system commands -files = !ls /usr : Capture system command output -files.s, files.l, files.n: "a b c", ['a','b','c'], 'a\nb\nc' - -History: - -_i, _ii, _iii : Previous, next previous, next next previous input -_i4, _ih[2:5] : Input history line 4, lines 2-4 -exec(_i81) : Execute input history line #81 again -%rep 81 : Edit input history line #81 -_, __, ___ : previous, next previous, next next previous output -_dh : Directory history -_oh : Output history -%hist : Command history of current session. -%hist -g foo : Search command history of (almost) all sessions for 'foo'. -%hist -g : Command history of (almost) all sessions. -%hist 1/2-8 : Command history containing lines 2-8 of session 1. -%hist 1/ ~2/ : Command history of session 1 and 2 sessions before current. -%hist ~8/1-~6/5 : Command history from line 1 of 8 sessions ago to - line 5 of 6 sessions ago. -%edit 0/ : Open editor to execute code with history of current session. - -Autocall: - -f 1,2 : f(1,2) # Off by default, enable with %autocall magic. -/f 1,2 : f(1,2) (forced autoparen) -,f 1 2 : f("1","2") -;f 1 2 : f("1 2") - -Remember: TAB completion works in many contexts, not just file names -or python names. - -The following magic functions are currently available: - -""" - -default_banner_parts = ["Python %s\n"%sys.version.split("\n")[0], - "Type 'copyright', 'credits' or 'license' for more information\n" , - "IPython {version} -- An enhanced Interactive Python. Type '?' for help.\n".format(version=release.version), -] - -default_banner = ''.join(default_banner_parts) diff --git a/contrib/python/ipython/py3/IPython/display.py b/contrib/python/ipython/py3/IPython/display.py deleted file mode 100644 index b7f64f25c9..0000000000 --- a/contrib/python/ipython/py3/IPython/display.py +++ /dev/null @@ -1,44 +0,0 @@ -"""Public API for display tools in IPython. -""" - -# ----------------------------------------------------------------------------- -# Copyright (C) 2012 The IPython Development Team -# -# Distributed under the terms of the BSD License. The full license is in -# the file COPYING, distributed as part of this software. -# ----------------------------------------------------------------------------- - -# ----------------------------------------------------------------------------- -# Imports -# ----------------------------------------------------------------------------- - -from IPython.core.display_functions import * -from IPython.core.display import ( - display_pretty, - display_html, - display_markdown, - display_svg, - display_png, - display_jpeg, - display_latex, - display_json, - display_javascript, - display_pdf, - DisplayObject, - TextDisplayObject, - Pretty, - HTML, - Markdown, - Math, - Latex, - SVG, - ProgressBar, - JSON, - GeoJSON, - Javascript, - Image, - set_matplotlib_formats, - set_matplotlib_close, - Video, -) -from IPython.lib.display import * diff --git a/contrib/python/ipython/py3/IPython/extensions/__init__.py b/contrib/python/ipython/py3/IPython/extensions/__init__.py deleted file mode 100644 index db7f79fca6..0000000000 --- a/contrib/python/ipython/py3/IPython/extensions/__init__.py +++ /dev/null @@ -1,2 +0,0 @@ -# -*- coding: utf-8 -*- -"""This directory is meant for IPython extensions.""" diff --git a/contrib/python/ipython/py3/IPython/extensions/autoreload.py b/contrib/python/ipython/py3/IPython/extensions/autoreload.py deleted file mode 100644 index 816d2f35ea..0000000000 --- a/contrib/python/ipython/py3/IPython/extensions/autoreload.py +++ /dev/null @@ -1,627 +0,0 @@ -"""IPython extension to reload modules before executing user code. - -``autoreload`` reloads modules automatically before entering the execution of -code typed at the IPython prompt. - -This makes for example the following workflow possible: - -.. sourcecode:: ipython - - In [1]: %load_ext autoreload - - In [2]: %autoreload 2 - - In [3]: from foo import some_function - - In [4]: some_function() - Out[4]: 42 - - In [5]: # open foo.py in an editor and change some_function to return 43 - - In [6]: some_function() - Out[6]: 43 - -The module was reloaded without reloading it explicitly, and the object -imported with ``from foo import ...`` was also updated. - -Usage -===== - -The following magic commands are provided: - -``%autoreload`` - - Reload all modules (except those excluded by ``%aimport``) - automatically now. - -``%autoreload 0`` - - Disable automatic reloading. - -``%autoreload 1`` - - Reload all modules imported with ``%aimport`` every time before - executing the Python code typed. - -``%autoreload 2`` - - Reload all modules (except those excluded by ``%aimport``) every - time before executing the Python code typed. - -``%autoreload 3`` - - Reload all modules AND autoload newly added objects - every time before executing the Python code typed. - -``%aimport`` - - List modules which are to be automatically imported or not to be imported. - -``%aimport foo`` - - Import module 'foo' and mark it to be autoreloaded for ``%autoreload 1`` - -``%aimport foo, bar`` - - Import modules 'foo', 'bar' and mark them to be autoreloaded for ``%autoreload 1`` - -``%aimport -foo`` - - Mark module 'foo' to not be autoreloaded. - -Caveats -======= - -Reloading Python modules in a reliable way is in general difficult, -and unexpected things may occur. ``%autoreload`` tries to work around -common pitfalls by replacing function code objects and parts of -classes previously in the module with new versions. This makes the -following things to work: - -- Functions and classes imported via 'from xxx import foo' are upgraded - to new versions when 'xxx' is reloaded. - -- Methods and properties of classes are upgraded on reload, so that - calling 'c.foo()' on an object 'c' created before the reload causes - the new code for 'foo' to be executed. - -Some of the known remaining caveats are: - -- Replacing code objects does not always succeed: changing a @property - in a class to an ordinary method or a method to a member variable - can cause problems (but in old objects only). - -- Functions that are removed (eg. via monkey-patching) from a module - before it is reloaded are not upgraded. - -- C extension modules cannot be reloaded, and so cannot be autoreloaded. -""" - -__skip_doctest__ = True - -# ----------------------------------------------------------------------------- -# Copyright (C) 2000 Thomas Heller -# Copyright (C) 2008 Pauli Virtanen <pav@iki.fi> -# Copyright (C) 2012 The IPython Development Team -# -# Distributed under the terms of the BSD License. The full license is in -# the file COPYING, distributed as part of this software. -# ----------------------------------------------------------------------------- -# -# This IPython module is written by Pauli Virtanen, based on the autoreload -# code by Thomas Heller. - -# ----------------------------------------------------------------------------- -# Imports -# ----------------------------------------------------------------------------- - -import os -import sys -import traceback -import types -import weakref -import gc -from importlib import import_module, reload -from importlib.util import source_from_cache - -# ------------------------------------------------------------------------------ -# Autoreload functionality -# ------------------------------------------------------------------------------ - - -class ModuleReloader: - enabled = False - """Whether this reloader is enabled""" - - check_all = True - """Autoreload all modules, not just those listed in 'modules'""" - - autoload_obj = False - """Autoreload all modules AND autoload all new objects""" - - def __init__(self, shell=None): - # Modules that failed to reload: {module: mtime-on-failed-reload, ...} - self.failed = {} - # Modules specially marked as autoreloadable. - self.modules = {} - # Modules specially marked as not autoreloadable. - self.skip_modules = {} - # (module-name, name) -> weakref, for replacing old code objects - self.old_objects = {} - # Module modification timestamps - self.modules_mtimes = {} - self.shell = shell - - # Cache module modification times - self.check(check_all=True, do_reload=False) - - def mark_module_skipped(self, module_name): - """Skip reloading the named module in the future""" - try: - del self.modules[module_name] - except KeyError: - pass - self.skip_modules[module_name] = True - - def mark_module_reloadable(self, module_name): - """Reload the named module in the future (if it is imported)""" - try: - del self.skip_modules[module_name] - except KeyError: - pass - self.modules[module_name] = True - - def aimport_module(self, module_name): - """Import a module, and mark it reloadable - - Returns - ------- - top_module : module - The imported module if it is top-level, or the top-level - top_name : module - Name of top_module - - """ - self.mark_module_reloadable(module_name) - - import_module(module_name) - top_name = module_name.split(".")[0] - top_module = sys.modules[top_name] - return top_module, top_name - - def filename_and_mtime(self, module): - if not hasattr(module, "__file__") or module.__file__ is None: - return None, None - - if getattr(module, "__name__", None) in [None, "__mp_main__", "__main__"]: - # we cannot reload(__main__) or reload(__mp_main__) - return None, None - - filename = module.__file__ - path, ext = os.path.splitext(filename) - - if ext.lower() == ".py": - py_filename = filename - else: - try: - py_filename = source_from_cache(filename) - except ValueError: - return None, None - - try: - pymtime = os.stat(py_filename).st_mtime - except OSError: - return None, None - - return py_filename, pymtime - - def check(self, check_all=False, do_reload=True): - """Check whether some modules need to be reloaded.""" - - if not self.enabled and not check_all: - return - - if check_all or self.check_all: - modules = list(sys.modules.keys()) - else: - modules = list(self.modules.keys()) - - for modname in modules: - m = sys.modules.get(modname, None) - - if modname in self.skip_modules: - continue - - py_filename, pymtime = self.filename_and_mtime(m) - if py_filename is None: - continue - - try: - if pymtime <= self.modules_mtimes[modname]: - continue - except KeyError: - self.modules_mtimes[modname] = pymtime - continue - else: - if self.failed.get(py_filename, None) == pymtime: - continue - - self.modules_mtimes[modname] = pymtime - - # If we've reached this point, we should try to reload the module - if do_reload: - try: - if self.autoload_obj: - superreload(m, reload, self.old_objects, self.shell) - else: - superreload(m, reload, self.old_objects) - if py_filename in self.failed: - del self.failed[py_filename] - except: - print( - "[autoreload of {} failed: {}]".format( - modname, traceback.format_exc(10) - ), - file=sys.stderr, - ) - self.failed[py_filename] = pymtime - - -# ------------------------------------------------------------------------------ -# superreload -# ------------------------------------------------------------------------------ - - -func_attrs = [ - "__code__", - "__defaults__", - "__doc__", - "__closure__", - "__globals__", - "__dict__", -] - - -def update_function(old, new): - """Upgrade the code object of a function""" - for name in func_attrs: - try: - setattr(old, name, getattr(new, name)) - except (AttributeError, TypeError): - pass - - -def update_instances(old, new): - """Use garbage collector to find all instances that refer to the old - class definition and update their __class__ to point to the new class - definition""" - - refs = gc.get_referrers(old) - - for ref in refs: - if type(ref) is old: - ref.__class__ = new - - -def update_class(old, new): - """Replace stuff in the __dict__ of a class, and upgrade - method code objects, and add new methods, if any""" - for key in list(old.__dict__.keys()): - old_obj = getattr(old, key) - try: - new_obj = getattr(new, key) - # explicitly checking that comparison returns True to handle - # cases where `==` doesn't return a boolean. - if (old_obj == new_obj) is True: - continue - except AttributeError: - # obsolete attribute: remove it - try: - delattr(old, key) - except (AttributeError, TypeError): - pass - continue - except ValueError: - # can't compare nested structures containing - # numpy arrays using `==` - pass - - if update_generic(old_obj, new_obj): - continue - - try: - setattr(old, key, getattr(new, key)) - except (AttributeError, TypeError): - pass # skip non-writable attributes - - for key in list(new.__dict__.keys()): - if key not in list(old.__dict__.keys()): - try: - setattr(old, key, getattr(new, key)) - except (AttributeError, TypeError): - pass # skip non-writable attributes - - # update all instances of class - update_instances(old, new) - - -def update_property(old, new): - """Replace get/set/del functions of a property""" - update_generic(old.fdel, new.fdel) - update_generic(old.fget, new.fget) - update_generic(old.fset, new.fset) - - -def isinstance2(a, b, typ): - return isinstance(a, typ) and isinstance(b, typ) - - -UPDATE_RULES = [ - (lambda a, b: isinstance2(a, b, type), update_class), - (lambda a, b: isinstance2(a, b, types.FunctionType), update_function), - (lambda a, b: isinstance2(a, b, property), update_property), -] -UPDATE_RULES.extend( - [ - ( - lambda a, b: isinstance2(a, b, types.MethodType), - lambda a, b: update_function(a.__func__, b.__func__), - ), - ] -) - - -def update_generic(a, b): - for type_check, update in UPDATE_RULES: - if type_check(a, b): - update(a, b) - return True - return False - - -class StrongRef: - def __init__(self, obj): - self.obj = obj - - def __call__(self): - return self.obj - - -mod_attrs = [ - "__name__", - "__doc__", - "__package__", - "__loader__", - "__spec__", - "__file__", - "__cached__", - "__builtins__", -] - - -def append_obj(module, d, name, obj, autoload=False): - in_module = hasattr(obj, "__module__") and obj.__module__ == module.__name__ - if autoload: - # check needed for module global built-ins - if not in_module and name in mod_attrs: - return False - else: - if not in_module: - return False - - key = (module.__name__, name) - try: - d.setdefault(key, []).append(weakref.ref(obj)) - except TypeError: - pass - return True - - -def superreload(module, reload=reload, old_objects=None, shell=None): - """Enhanced version of the builtin reload function. - - superreload remembers objects previously in the module, and - - - upgrades the class dictionary of every old class in the module - - upgrades the code object of every old function and method - - clears the module's namespace before reloading - - """ - if old_objects is None: - old_objects = {} - - # collect old objects in the module - for name, obj in list(module.__dict__.items()): - if not append_obj(module, old_objects, name, obj): - continue - key = (module.__name__, name) - try: - old_objects.setdefault(key, []).append(weakref.ref(obj)) - except TypeError: - pass - - # reload module - try: - # clear namespace first from old cruft - old_dict = module.__dict__.copy() - old_name = module.__name__ - module.__dict__.clear() - module.__dict__["__name__"] = old_name - module.__dict__["__loader__"] = old_dict["__loader__"] - except (TypeError, AttributeError, KeyError): - pass - - try: - module = reload(module) - except: - # restore module dictionary on failed reload - module.__dict__.update(old_dict) - raise - - # iterate over all objects and update functions & classes - for name, new_obj in list(module.__dict__.items()): - key = (module.__name__, name) - if key not in old_objects: - # here 'shell' acts both as a flag and as an output var - if ( - shell is None - or name == "Enum" - or not append_obj(module, old_objects, name, new_obj, True) - ): - continue - shell.user_ns[name] = new_obj - - new_refs = [] - for old_ref in old_objects[key]: - old_obj = old_ref() - if old_obj is None: - continue - new_refs.append(old_ref) - update_generic(old_obj, new_obj) - - if new_refs: - old_objects[key] = new_refs - else: - del old_objects[key] - - return module - - -# ------------------------------------------------------------------------------ -# IPython connectivity -# ------------------------------------------------------------------------------ - -from IPython.core.magic import Magics, magics_class, line_magic - - -@magics_class -class AutoreloadMagics(Magics): - def __init__(self, *a, **kw): - super().__init__(*a, **kw) - self._reloader = ModuleReloader(self.shell) - self._reloader.check_all = False - self._reloader.autoload_obj = False - self.loaded_modules = set(sys.modules) - - @line_magic - def autoreload(self, parameter_s=""): - r"""%autoreload => Reload modules automatically - - %autoreload - Reload all modules (except those excluded by %aimport) automatically - now. - - %autoreload 0 - Disable automatic reloading. - - %autoreload 1 - Reload all modules imported with %aimport every time before executing - the Python code typed. - - %autoreload 2 - Reload all modules (except those excluded by %aimport) every time - before executing the Python code typed. - - Reloading Python modules in a reliable way is in general - difficult, and unexpected things may occur. %autoreload tries to - work around common pitfalls by replacing function code objects and - parts of classes previously in the module with new versions. This - makes the following things to work: - - - Functions and classes imported via 'from xxx import foo' are upgraded - to new versions when 'xxx' is reloaded. - - - Methods and properties of classes are upgraded on reload, so that - calling 'c.foo()' on an object 'c' created before the reload causes - the new code for 'foo' to be executed. - - Some of the known remaining caveats are: - - - Replacing code objects does not always succeed: changing a @property - in a class to an ordinary method or a method to a member variable - can cause problems (but in old objects only). - - - Functions that are removed (eg. via monkey-patching) from a module - before it is reloaded are not upgraded. - - - C extension modules cannot be reloaded, and so cannot be - autoreloaded. - - """ - if parameter_s == "": - self._reloader.check(True) - elif parameter_s == "0": - self._reloader.enabled = False - elif parameter_s == "1": - self._reloader.check_all = False - self._reloader.enabled = True - elif parameter_s == "2": - self._reloader.check_all = True - self._reloader.enabled = True - self._reloader.enabled = True - elif parameter_s == "3": - self._reloader.check_all = True - self._reloader.enabled = True - self._reloader.autoload_obj = True - - @line_magic - def aimport(self, parameter_s="", stream=None): - """%aimport => Import modules for automatic reloading. - - %aimport - List modules to automatically import and not to import. - - %aimport foo - Import module 'foo' and mark it to be autoreloaded for %autoreload 1 - - %aimport foo, bar - Import modules 'foo', 'bar' and mark them to be autoreloaded for %autoreload 1 - - %aimport -foo - Mark module 'foo' to not be autoreloaded for %autoreload 1 - """ - modname = parameter_s - if not modname: - to_reload = sorted(self._reloader.modules.keys()) - to_skip = sorted(self._reloader.skip_modules.keys()) - if stream is None: - stream = sys.stdout - if self._reloader.check_all: - stream.write("Modules to reload:\nall-except-skipped\n") - else: - stream.write("Modules to reload:\n%s\n" % " ".join(to_reload)) - stream.write("\nModules to skip:\n%s\n" % " ".join(to_skip)) - elif modname.startswith("-"): - modname = modname[1:] - self._reloader.mark_module_skipped(modname) - else: - for _module in [_.strip() for _ in modname.split(",")]: - top_module, top_name = self._reloader.aimport_module(_module) - - # Inject module to user namespace - self.shell.push({top_name: top_module}) - - def pre_run_cell(self): - if self._reloader.enabled: - try: - self._reloader.check() - except: - pass - - def post_execute_hook(self): - """Cache the modification times of any modules imported in this execution""" - newly_loaded_modules = set(sys.modules) - self.loaded_modules - for modname in newly_loaded_modules: - _, pymtime = self._reloader.filename_and_mtime(sys.modules[modname]) - if pymtime is not None: - self._reloader.modules_mtimes[modname] = pymtime - - self.loaded_modules.update(newly_loaded_modules) - - -def load_ipython_extension(ip): - """Load the extension in IPython.""" - auto_reload = AutoreloadMagics(ip) - ip.register_magics(auto_reload) - ip.events.register("pre_run_cell", auto_reload.pre_run_cell) - ip.events.register("post_execute", auto_reload.post_execute_hook) diff --git a/contrib/python/ipython/py3/IPython/extensions/storemagic.py b/contrib/python/ipython/py3/IPython/extensions/storemagic.py deleted file mode 100644 index d9d00f14b9..0000000000 --- a/contrib/python/ipython/py3/IPython/extensions/storemagic.py +++ /dev/null @@ -1,236 +0,0 @@ -# -*- coding: utf-8 -*- -""" -%store magic for lightweight persistence. - -Stores variables, aliases and macros in IPython's database. - -To automatically restore stored variables at startup, add this to your -:file:`ipython_config.py` file:: - - c.StoreMagics.autorestore = True -""" - -# Copyright (c) IPython Development Team. -# Distributed under the terms of the Modified BSD License. - -import inspect, os, sys, textwrap - -from IPython.core.error import UsageError -from IPython.core.magic import Magics, magics_class, line_magic -from IPython.testing.skipdoctest import skip_doctest -from traitlets import Bool - - -def restore_aliases(ip, alias=None): - staliases = ip.db.get('stored_aliases', {}) - if alias is None: - for k,v in staliases.items(): - #print "restore alias",k,v # dbg - #self.alias_table[k] = v - ip.alias_manager.define_alias(k,v) - else: - ip.alias_manager.define_alias(alias, staliases[alias]) - - -def refresh_variables(ip): - db = ip.db - for key in db.keys('autorestore/*'): - # strip autorestore - justkey = os.path.basename(key) - try: - obj = db[key] - except KeyError: - print("Unable to restore variable '%s', ignoring (use %%store -d to forget!)" % justkey) - print("The error was:", sys.exc_info()[0]) - else: - #print "restored",justkey,"=",obj #dbg - ip.user_ns[justkey] = obj - - -def restore_dhist(ip): - ip.user_ns['_dh'] = ip.db.get('dhist',[]) - - -def restore_data(ip): - refresh_variables(ip) - restore_aliases(ip) - restore_dhist(ip) - - -@magics_class -class StoreMagics(Magics): - """Lightweight persistence for python variables. - - Provides the %store magic.""" - - autorestore = Bool(False, help= - """If True, any %store-d variables will be automatically restored - when IPython starts. - """ - ).tag(config=True) - - def __init__(self, shell): - super(StoreMagics, self).__init__(shell=shell) - self.shell.configurables.append(self) - if self.autorestore: - restore_data(self.shell) - - @skip_doctest - @line_magic - def store(self, parameter_s=''): - """Lightweight persistence for python variables. - - Example:: - - In [1]: l = ['hello',10,'world'] - In [2]: %store l - Stored 'l' (list) - In [3]: exit - - (IPython session is closed and started again...) - - ville@badger:~$ ipython - In [1]: l - NameError: name 'l' is not defined - In [2]: %store -r - In [3]: l - Out[3]: ['hello', 10, 'world'] - - Usage: - - * ``%store`` - Show list of all variables and their current - values - * ``%store spam bar`` - Store the *current* value of the variables spam - and bar to disk - * ``%store -d spam`` - Remove the variable and its value from storage - * ``%store -z`` - Remove all variables from storage - * ``%store -r`` - Refresh all variables, aliases and directory history - from store (overwrite current vals) - * ``%store -r spam bar`` - Refresh specified variables and aliases from store - (delete current val) - * ``%store foo >a.txt`` - Store value of foo to new file a.txt - * ``%store foo >>a.txt`` - Append value of foo to file a.txt - - It should be noted that if you change the value of a variable, you - need to %store it again if you want to persist the new value. - - Note also that the variables will need to be pickleable; most basic - python types can be safely %store'd. - - Also aliases can be %store'd across sessions. - To remove an alias from the storage, use the %unalias magic. - """ - - opts,argsl = self.parse_options(parameter_s,'drz',mode='string') - args = argsl.split() - ip = self.shell - db = ip.db - # delete - if 'd' in opts: - try: - todel = args[0] - except IndexError as e: - raise UsageError('You must provide the variable to forget') from e - else: - try: - del db['autorestore/' + todel] - except BaseException as e: - raise UsageError("Can't delete variable '%s'" % todel) from e - # reset - elif 'z' in opts: - for k in db.keys('autorestore/*'): - del db[k] - - elif 'r' in opts: - if args: - for arg in args: - try: - obj = db['autorestore/' + arg] - except KeyError: - try: - restore_aliases(ip, alias=arg) - except KeyError: - print("no stored variable or alias %s" % arg) - else: - ip.user_ns[arg] = obj - else: - restore_data(ip) - - # run without arguments -> list variables & values - elif not args: - vars = db.keys('autorestore/*') - vars.sort() - if vars: - size = max(map(len, vars)) - else: - size = 0 - - print('Stored variables and their in-db values:') - fmt = '%-'+str(size)+'s -> %s' - get = db.get - for var in vars: - justkey = os.path.basename(var) - # print 30 first characters from every var - print(fmt % (justkey, repr(get(var, '<unavailable>'))[:50])) - - # default action - store the variable - else: - # %store foo >file.txt or >>file.txt - if len(args) > 1 and args[1].startswith(">"): - fnam = os.path.expanduser(args[1].lstrip(">").lstrip()) - if args[1].startswith(">>"): - fil = open(fnam, "a", encoding="utf-8") - else: - fil = open(fnam, "w", encoding="utf-8") - with fil: - obj = ip.ev(args[0]) - print("Writing '%s' (%s) to file '%s'." % (args[0], - obj.__class__.__name__, fnam)) - - if not isinstance (obj, str): - from pprint import pprint - pprint(obj, fil) - else: - fil.write(obj) - if not obj.endswith('\n'): - fil.write('\n') - - return - - # %store foo - for arg in args: - try: - obj = ip.user_ns[arg] - except KeyError: - # it might be an alias - name = arg - try: - cmd = ip.alias_manager.retrieve_alias(name) - except ValueError as e: - raise UsageError("Unknown variable '%s'" % name) from e - - staliases = db.get('stored_aliases',{}) - staliases[name] = cmd - db['stored_aliases'] = staliases - print("Alias stored: %s (%s)" % (name, cmd)) - return - - else: - modname = getattr(inspect.getmodule(obj), '__name__', '') - if modname == '__main__': - print(textwrap.dedent("""\ - Warning:%s is %s - Proper storage of interactively declared classes (or instances - of those classes) is not possible! Only instances - of classes in real modules on file system can be %%store'd. - """ % (arg, obj) )) - return - #pickled = pickle.dumps(obj) - db[ 'autorestore/' + arg ] = obj - print("Stored '%s' (%s)" % (arg, obj.__class__.__name__)) - - -def load_ipython_extension(ip): - """Load the extension in IPython.""" - ip.register_magics(StoreMagics) - diff --git a/contrib/python/ipython/py3/IPython/external/__init__.py b/contrib/python/ipython/py3/IPython/external/__init__.py deleted file mode 100644 index eedc338eb8..0000000000 --- a/contrib/python/ipython/py3/IPython/external/__init__.py +++ /dev/null @@ -1,7 +0,0 @@ -""" -This package contains all third-party modules bundled with IPython. -""" - -from typing import List - -__all__: List[str] = [] diff --git a/contrib/python/ipython/py3/IPython/external/qt_for_kernel.py b/contrib/python/ipython/py3/IPython/external/qt_for_kernel.py deleted file mode 100644 index b3168f6e2e..0000000000 --- a/contrib/python/ipython/py3/IPython/external/qt_for_kernel.py +++ /dev/null @@ -1,128 +0,0 @@ -""" Import Qt in a manner suitable for an IPython kernel. - -This is the import used for the `gui=qt` or `matplotlib=qt` initialization. - -Import Priority: - -if Qt has been imported anywhere else: - use that - -if matplotlib has been imported and doesn't support v2 (<= 1.0.1): - use PyQt4 @v1 - -Next, ask QT_API env variable - -if QT_API not set: - ask matplotlib what it's using. If Qt4Agg or Qt5Agg, then use the - version matplotlib is configured with - - else: (matplotlib said nothing) - # this is the default path - nobody told us anything - try in this order: - PyQt default version, PySide, PyQt5 -else: - use what QT_API says - -""" -# NOTE: This is no longer an external, third-party module, and should be -# considered part of IPython. For compatibility however, it is being kept in -# IPython/external. - -import os -import sys - -from IPython.external.qt_loaders import ( - load_qt, - loaded_api, - enum_factory, - # QT6 - QT_API_PYQT6, - QT_API_PYSIDE6, - # QT5 - QT_API_PYQT5, - QT_API_PYSIDE2, - # QT4 - QT_API_PYQTv1, - QT_API_PYQT, - QT_API_PYSIDE, - # default - QT_API_PYQT_DEFAULT, -) - -_qt_apis = ( - # QT6 - QT_API_PYQT6, - QT_API_PYSIDE6, - # QT5 - QT_API_PYQT5, - QT_API_PYSIDE2, - # QT4 - QT_API_PYQTv1, - QT_API_PYQT, - QT_API_PYSIDE, - # default - QT_API_PYQT_DEFAULT, -) - - -def matplotlib_options(mpl): - """Constraints placed on an imported matplotlib.""" - if mpl is None: - return - backend = mpl.rcParams.get('backend', None) - if backend == 'Qt4Agg': - mpqt = mpl.rcParams.get('backend.qt4', None) - if mpqt is None: - return None - if mpqt.lower() == 'pyside': - return [QT_API_PYSIDE] - elif mpqt.lower() == 'pyqt4': - return [QT_API_PYQT_DEFAULT] - elif mpqt.lower() == 'pyqt4v2': - return [QT_API_PYQT] - raise ImportError("unhandled value for backend.qt4 from matplotlib: %r" % - mpqt) - elif backend == 'Qt5Agg': - mpqt = mpl.rcParams.get('backend.qt5', None) - if mpqt is None: - return None - if mpqt.lower() == 'pyqt5': - return [QT_API_PYQT5] - raise ImportError("unhandled value for backend.qt5 from matplotlib: %r" % - mpqt) - -def get_options(): - """Return a list of acceptable QT APIs, in decreasing order of preference.""" - #already imported Qt somewhere. Use that - loaded = loaded_api() - if loaded is not None: - return [loaded] - - mpl = sys.modules.get('matplotlib', None) - - if mpl is not None and tuple(mpl.__version__.split(".")) < ("1", "0", "2"): - # 1.0.1 only supports PyQt4 v1 - return [QT_API_PYQT_DEFAULT] - - qt_api = os.environ.get('QT_API', None) - if qt_api is None: - #no ETS variable. Ask mpl, then use default fallback path - return matplotlib_options(mpl) or [ - QT_API_PYQT_DEFAULT, - QT_API_PYQT6, - QT_API_PYSIDE6, - QT_API_PYQT5, - QT_API_PYSIDE2, - QT_API_PYQT, - QT_API_PYSIDE, - ] - elif qt_api not in _qt_apis: - raise RuntimeError("Invalid Qt API %r, valid values are: %r" % - (qt_api, ', '.join(_qt_apis))) - else: - return [qt_api] - - -api_opts = get_options() -QtCore, QtGui, QtSvg, QT_API = load_qt(api_opts) -enum_helper = enum_factory(QT_API, QtCore) diff --git a/contrib/python/ipython/py3/IPython/external/qt_loaders.py b/contrib/python/ipython/py3/IPython/external/qt_loaders.py deleted file mode 100644 index 39ea298460..0000000000 --- a/contrib/python/ipython/py3/IPython/external/qt_loaders.py +++ /dev/null @@ -1,399 +0,0 @@ -""" -This module contains factory functions that attempt -to return Qt submodules from the various python Qt bindings. - -It also protects against double-importing Qt with different -bindings, which is unstable and likely to crash - -This is used primarily by qt and qt_for_kernel, and shouldn't -be accessed directly from the outside -""" -import importlib.abc -import sys -import types -from functools import partial, lru_cache -import operator - -# ### Available APIs. -# Qt6 -QT_API_PYQT6 = "pyqt6" -QT_API_PYSIDE6 = "pyside6" - -# Qt5 -QT_API_PYQT5 = 'pyqt5' -QT_API_PYSIDE2 = 'pyside2' - -# Qt4 -QT_API_PYQT = "pyqt" # Force version 2 -QT_API_PYQTv1 = "pyqtv1" # Force version 2 -QT_API_PYSIDE = "pyside" - -QT_API_PYQT_DEFAULT = "pyqtdefault" # use system default for version 1 vs. 2 - -api_to_module = { - # Qt6 - QT_API_PYQT6: "PyQt6", - QT_API_PYSIDE6: "PySide6", - # Qt5 - QT_API_PYQT5: "PyQt5", - QT_API_PYSIDE2: "PySide2", - # Qt4 - QT_API_PYSIDE: "PySide", - QT_API_PYQT: "PyQt4", - QT_API_PYQTv1: "PyQt4", - # default - QT_API_PYQT_DEFAULT: "PyQt6", -} - - -class ImportDenier(importlib.abc.MetaPathFinder): - """Import Hook that will guard against bad Qt imports - once IPython commits to a specific binding - """ - - def __init__(self): - self.__forbidden = set() - - def forbid(self, module_name): - sys.modules.pop(module_name, None) - self.__forbidden.add(module_name) - - def find_spec(self, fullname, path, target=None): - if path: - return - if fullname in self.__forbidden: - raise ImportError( - """ - Importing %s disabled by IPython, which has - already imported an Incompatible QT Binding: %s - """ - % (fullname, loaded_api()) - ) - - -ID = ImportDenier() -sys.meta_path.insert(0, ID) - - -def commit_api(api): - """Commit to a particular API, and trigger ImportErrors on subsequent - dangerous imports""" - modules = set(api_to_module.values()) - - modules.remove(api_to_module[api]) - for mod in modules: - ID.forbid(mod) - - -def loaded_api(): - """Return which API is loaded, if any - - If this returns anything besides None, - importing any other Qt binding is unsafe. - - Returns - ------- - None, 'pyside6', 'pyqt6', 'pyside2', 'pyside', 'pyqt', 'pyqt5', 'pyqtv1' - """ - if sys.modules.get("PyQt6.QtCore"): - return QT_API_PYQT6 - elif sys.modules.get("PySide6.QtCore"): - return QT_API_PYSIDE6 - elif sys.modules.get("PyQt5.QtCore"): - return QT_API_PYQT5 - elif sys.modules.get("PySide2.QtCore"): - return QT_API_PYSIDE2 - elif sys.modules.get("PyQt4.QtCore"): - if qtapi_version() == 2: - return QT_API_PYQT - else: - return QT_API_PYQTv1 - elif sys.modules.get("PySide.QtCore"): - return QT_API_PYSIDE - - return None - - -def has_binding(api): - """Safely check for PyQt4/5, PySide or PySide2, without importing submodules - - Parameters - ---------- - api : str [ 'pyqtv1' | 'pyqt' | 'pyqt5' | 'pyside' | 'pyside2' | 'pyqtdefault'] - Which module to check for - - Returns - ------- - True if the relevant module appears to be importable - """ - module_name = api_to_module[api] - from importlib.util import find_spec - - required = ['QtCore', 'QtGui', 'QtSvg'] - if api in (QT_API_PYQT5, QT_API_PYSIDE2, QT_API_PYQT6, QT_API_PYSIDE6): - # QT5 requires QtWidgets too - required.append('QtWidgets') - - for submod in required: - try: - spec = find_spec('%s.%s' % (module_name, submod)) - except ImportError: - # Package (e.g. PyQt5) not found - return False - else: - if spec is None: - # Submodule (e.g. PyQt5.QtCore) not found - return False - - if api == QT_API_PYSIDE: - # We can also safely check PySide version - import PySide - - return PySide.__version_info__ >= (1, 0, 3) - - return True - - -def qtapi_version(): - """Return which QString API has been set, if any - - Returns - ------- - The QString API version (1 or 2), or None if not set - """ - try: - import sip - except ImportError: - # as of PyQt5 5.11, sip is no longer available as a top-level - # module and needs to be imported from the PyQt5 namespace - try: - from PyQt5 import sip - except ImportError: - return - try: - return sip.getapi('QString') - except ValueError: - return - - -def can_import(api): - """Safely query whether an API is importable, without importing it""" - if not has_binding(api): - return False - - current = loaded_api() - if api == QT_API_PYQT_DEFAULT: - return current in [QT_API_PYQT6, None] - else: - return current in [api, None] - - -def import_pyqt4(version=2): - """ - Import PyQt4 - - Parameters - ---------- - version : 1, 2, or None - Which QString/QVariant API to use. Set to None to use the system - default - ImportErrors raised within this function are non-recoverable - """ - # The new-style string API (version=2) automatically - # converts QStrings to Unicode Python strings. Also, automatically unpacks - # QVariants to their underlying objects. - import sip - - if version is not None: - sip.setapi('QString', version) - sip.setapi('QVariant', version) - - from PyQt4 import QtGui, QtCore, QtSvg - - if QtCore.PYQT_VERSION < 0x040700: - raise ImportError("IPython requires PyQt4 >= 4.7, found %s" % - QtCore.PYQT_VERSION_STR) - - # Alias PyQt-specific functions for PySide compatibility. - QtCore.Signal = QtCore.pyqtSignal - QtCore.Slot = QtCore.pyqtSlot - - # query for the API version (in case version == None) - version = sip.getapi('QString') - api = QT_API_PYQTv1 if version == 1 else QT_API_PYQT - return QtCore, QtGui, QtSvg, api - - -def import_pyqt5(): - """ - Import PyQt5 - - ImportErrors raised within this function are non-recoverable - """ - - from PyQt5 import QtCore, QtSvg, QtWidgets, QtGui - - # Alias PyQt-specific functions for PySide compatibility. - QtCore.Signal = QtCore.pyqtSignal - QtCore.Slot = QtCore.pyqtSlot - - # Join QtGui and QtWidgets for Qt4 compatibility. - QtGuiCompat = types.ModuleType('QtGuiCompat') - QtGuiCompat.__dict__.update(QtGui.__dict__) - QtGuiCompat.__dict__.update(QtWidgets.__dict__) - - api = QT_API_PYQT5 - return QtCore, QtGuiCompat, QtSvg, api - - -def import_pyqt6(): - """ - Import PyQt6 - - ImportErrors raised within this function are non-recoverable - """ - - from PyQt6 import QtCore, QtSvg, QtWidgets, QtGui - - # Alias PyQt-specific functions for PySide compatibility. - QtCore.Signal = QtCore.pyqtSignal - QtCore.Slot = QtCore.pyqtSlot - - # Join QtGui and QtWidgets for Qt4 compatibility. - QtGuiCompat = types.ModuleType("QtGuiCompat") - QtGuiCompat.__dict__.update(QtGui.__dict__) - QtGuiCompat.__dict__.update(QtWidgets.__dict__) - - api = QT_API_PYQT6 - return QtCore, QtGuiCompat, QtSvg, api - - -def import_pyside(): - """ - Import PySide - - ImportErrors raised within this function are non-recoverable - """ - from PySide import QtGui, QtCore, QtSvg - return QtCore, QtGui, QtSvg, QT_API_PYSIDE - -def import_pyside2(): - """ - Import PySide2 - - ImportErrors raised within this function are non-recoverable - """ - from PySide2 import QtGui, QtCore, QtSvg, QtWidgets, QtPrintSupport - - # Join QtGui and QtWidgets for Qt4 compatibility. - QtGuiCompat = types.ModuleType('QtGuiCompat') - QtGuiCompat.__dict__.update(QtGui.__dict__) - QtGuiCompat.__dict__.update(QtWidgets.__dict__) - QtGuiCompat.__dict__.update(QtPrintSupport.__dict__) - - return QtCore, QtGuiCompat, QtSvg, QT_API_PYSIDE2 - - -def import_pyside6(): - """ - Import PySide6 - - ImportErrors raised within this function are non-recoverable - """ - from PySide6 import QtGui, QtCore, QtSvg, QtWidgets, QtPrintSupport - - # Join QtGui and QtWidgets for Qt4 compatibility. - QtGuiCompat = types.ModuleType("QtGuiCompat") - QtGuiCompat.__dict__.update(QtGui.__dict__) - QtGuiCompat.__dict__.update(QtWidgets.__dict__) - QtGuiCompat.__dict__.update(QtPrintSupport.__dict__) - - return QtCore, QtGuiCompat, QtSvg, QT_API_PYSIDE6 - - -def load_qt(api_options): - """ - Attempt to import Qt, given a preference list - of permissible bindings - - It is safe to call this function multiple times. - - Parameters - ---------- - api_options : List of strings - The order of APIs to try. Valid items are 'pyside', 'pyside2', - 'pyqt', 'pyqt5', 'pyqtv1' and 'pyqtdefault' - - Returns - ------- - A tuple of QtCore, QtGui, QtSvg, QT_API - The first three are the Qt modules. The last is the - string indicating which module was loaded. - - Raises - ------ - ImportError, if it isn't possible to import any requested - bindings (either because they aren't installed, or because - an incompatible library has already been installed) - """ - loaders = { - # Qt6 - QT_API_PYQT6: import_pyqt6, - QT_API_PYSIDE6: import_pyside6, - # Qt5 - QT_API_PYQT5: import_pyqt5, - QT_API_PYSIDE2: import_pyside2, - # Qt4 - QT_API_PYSIDE: import_pyside, - QT_API_PYQT: import_pyqt4, - QT_API_PYQTv1: partial(import_pyqt4, version=1), - # default - QT_API_PYQT_DEFAULT: import_pyqt6, - } - - for api in api_options: - - if api not in loaders: - raise RuntimeError( - "Invalid Qt API %r, valid values are: %s" % - (api, ", ".join(["%r" % k for k in loaders.keys()]))) - - if not can_import(api): - continue - - #cannot safely recover from an ImportError during this - result = loaders[api]() - api = result[-1] # changed if api = QT_API_PYQT_DEFAULT - commit_api(api) - return result - else: - raise ImportError(""" - Could not load requested Qt binding. Please ensure that - PyQt4 >= 4.7, PyQt5, PySide >= 1.0.3 or PySide2 is available, - and only one is imported per session. - - Currently-imported Qt library: %r - PyQt4 available (requires QtCore, QtGui, QtSvg): %s - PyQt5 available (requires QtCore, QtGui, QtSvg, QtWidgets): %s - PySide >= 1.0.3 installed: %s - PySide2 installed: %s - Tried to load: %r - """ % (loaded_api(), - has_binding(QT_API_PYQT), - has_binding(QT_API_PYQT5), - has_binding(QT_API_PYSIDE), - has_binding(QT_API_PYSIDE2), - api_options)) - - -def enum_factory(QT_API, QtCore): - """Construct an enum helper to account for PyQt5 <-> PyQt6 changes.""" - - @lru_cache(None) - def _enum(name): - # foo.bar.Enum.Entry (PyQt6) <=> foo.bar.Entry (non-PyQt6). - return operator.attrgetter( - name if QT_API == QT_API_PYQT6 else name.rpartition(".")[0] - )(sys.modules[QtCore.__package__]) - - return _enum diff --git a/contrib/python/ipython/py3/IPython/lib/__init__.py b/contrib/python/ipython/py3/IPython/lib/__init__.py deleted file mode 100644 index 94b8ade4ec..0000000000 --- a/contrib/python/ipython/py3/IPython/lib/__init__.py +++ /dev/null @@ -1,11 +0,0 @@ -# encoding: utf-8 -""" -Extra capabilities for IPython -""" - -#----------------------------------------------------------------------------- -# Copyright (C) 2008-2011 The IPython Development Team -# -# Distributed under the terms of the BSD License. The full license is in -# the file COPYING, distributed as part of this software. -#----------------------------------------------------------------------------- diff --git a/contrib/python/ipython/py3/IPython/lib/backgroundjobs.py b/contrib/python/ipython/py3/IPython/lib/backgroundjobs.py deleted file mode 100644 index e7ad51eb67..0000000000 --- a/contrib/python/ipython/py3/IPython/lib/backgroundjobs.py +++ /dev/null @@ -1,491 +0,0 @@ -# -*- coding: utf-8 -*- -"""Manage background (threaded) jobs conveniently from an interactive shell. - -This module provides a BackgroundJobManager class. This is the main class -meant for public usage, it implements an object which can create and manage -new background jobs. - -It also provides the actual job classes managed by these BackgroundJobManager -objects, see their docstrings below. - - -This system was inspired by discussions with B. Granger and the -BackgroundCommand class described in the book Python Scripting for -Computational Science, by H. P. Langtangen: - -http://folk.uio.no/hpl/scripting - -(although ultimately no code from this text was used, as IPython's system is a -separate implementation). - -An example notebook is provided in our documentation illustrating interactive -use of the system. -""" - -#***************************************************************************** -# Copyright (C) 2005-2006 Fernando Perez <fperez@colorado.edu> -# -# Distributed under the terms of the BSD License. The full license is in -# the file COPYING, distributed as part of this software. -#***************************************************************************** - -# Code begins -import sys -import threading - -from IPython import get_ipython -from IPython.core.ultratb import AutoFormattedTB -from logging import error, debug - - -class BackgroundJobManager(object): - """Class to manage a pool of backgrounded threaded jobs. - - Below, we assume that 'jobs' is a BackgroundJobManager instance. - - Usage summary (see the method docstrings for details): - - jobs.new(...) -> start a new job - - jobs() or jobs.status() -> print status summary of all jobs - - jobs[N] -> returns job number N. - - foo = jobs[N].result -> assign to variable foo the result of job N - - jobs[N].traceback() -> print the traceback of dead job N - - jobs.remove(N) -> remove (finished) job N - - jobs.flush() -> remove all finished jobs - - As a convenience feature, BackgroundJobManager instances provide the - utility result and traceback methods which retrieve the corresponding - information from the jobs list: - - jobs.result(N) <--> jobs[N].result - jobs.traceback(N) <--> jobs[N].traceback() - - While this appears minor, it allows you to use tab completion - interactively on the job manager instance. - """ - - def __init__(self): - # Lists for job management, accessed via a property to ensure they're - # up to date.x - self._running = [] - self._completed = [] - self._dead = [] - # A dict of all jobs, so users can easily access any of them - self.all = {} - # For reporting - self._comp_report = [] - self._dead_report = [] - # Store status codes locally for fast lookups - self._s_created = BackgroundJobBase.stat_created_c - self._s_running = BackgroundJobBase.stat_running_c - self._s_completed = BackgroundJobBase.stat_completed_c - self._s_dead = BackgroundJobBase.stat_dead_c - self._current_job_id = 0 - - @property - def running(self): - self._update_status() - return self._running - - @property - def dead(self): - self._update_status() - return self._dead - - @property - def completed(self): - self._update_status() - return self._completed - - def new(self, func_or_exp, *args, **kwargs): - """Add a new background job and start it in a separate thread. - - There are two types of jobs which can be created: - - 1. Jobs based on expressions which can be passed to an eval() call. - The expression must be given as a string. For example: - - job_manager.new('myfunc(x,y,z=1)'[,glob[,loc]]) - - The given expression is passed to eval(), along with the optional - global/local dicts provided. If no dicts are given, they are - extracted automatically from the caller's frame. - - A Python statement is NOT a valid eval() expression. Basically, you - can only use as an eval() argument something which can go on the right - of an '=' sign and be assigned to a variable. - - For example,"print 'hello'" is not valid, but '2+3' is. - - 2. Jobs given a function object, optionally passing additional - positional arguments: - - job_manager.new(myfunc, x, y) - - The function is called with the given arguments. - - If you need to pass keyword arguments to your function, you must - supply them as a dict named kw: - - job_manager.new(myfunc, x, y, kw=dict(z=1)) - - The reason for this asymmetry is that the new() method needs to - maintain access to its own keywords, and this prevents name collisions - between arguments to new() and arguments to your own functions. - - In both cases, the result is stored in the job.result field of the - background job object. - - You can set `daemon` attribute of the thread by giving the keyword - argument `daemon`. - - Notes and caveats: - - 1. All threads running share the same standard output. Thus, if your - background jobs generate output, it will come out on top of whatever - you are currently writing. For this reason, background jobs are best - used with silent functions which simply return their output. - - 2. Threads also all work within the same global namespace, and this - system does not lock interactive variables. So if you send job to the - background which operates on a mutable object for a long time, and - start modifying that same mutable object interactively (or in another - backgrounded job), all sorts of bizarre behaviour will occur. - - 3. If a background job is spending a lot of time inside a C extension - module which does not release the Python Global Interpreter Lock - (GIL), this will block the IPython prompt. This is simply because the - Python interpreter can only switch between threads at Python - bytecodes. While the execution is inside C code, the interpreter must - simply wait unless the extension module releases the GIL. - - 4. There is no way, due to limitations in the Python threads library, - to kill a thread once it has started.""" - - if callable(func_or_exp): - kw = kwargs.get('kw',{}) - job = BackgroundJobFunc(func_or_exp,*args,**kw) - elif isinstance(func_or_exp, str): - if not args: - frame = sys._getframe(1) - glob, loc = frame.f_globals, frame.f_locals - elif len(args)==1: - glob = loc = args[0] - elif len(args)==2: - glob,loc = args - else: - raise ValueError( - 'Expression jobs take at most 2 args (globals,locals)') - job = BackgroundJobExpr(func_or_exp, glob, loc) - else: - raise TypeError('invalid args for new job') - - if kwargs.get('daemon', False): - job.daemon = True - job.num = self._current_job_id - self._current_job_id += 1 - self.running.append(job) - self.all[job.num] = job - debug('Starting job # %s in a separate thread.' % job.num) - job.start() - return job - - def __getitem__(self, job_key): - num = job_key if isinstance(job_key, int) else job_key.num - return self.all[num] - - def __call__(self): - """An alias to self.status(), - - This allows you to simply call a job manager instance much like the - Unix `jobs` shell command.""" - - return self.status() - - def _update_status(self): - """Update the status of the job lists. - - This method moves finished jobs to one of two lists: - - self.completed: jobs which completed successfully - - self.dead: jobs which finished but died. - - It also copies those jobs to corresponding _report lists. These lists - are used to report jobs completed/dead since the last update, and are - then cleared by the reporting function after each call.""" - - # Status codes - srun, scomp, sdead = self._s_running, self._s_completed, self._s_dead - # State lists, use the actual lists b/c the public names are properties - # that call this very function on access - running, completed, dead = self._running, self._completed, self._dead - - # Now, update all state lists - for num, job in enumerate(running): - stat = job.stat_code - if stat == srun: - continue - elif stat == scomp: - completed.append(job) - self._comp_report.append(job) - running[num] = False - elif stat == sdead: - dead.append(job) - self._dead_report.append(job) - running[num] = False - # Remove dead/completed jobs from running list - running[:] = filter(None, running) - - def _group_report(self,group,name): - """Report summary for a given job group. - - Return True if the group had any elements.""" - - if group: - print('%s jobs:' % name) - for job in group: - print('%s : %s' % (job.num,job)) - print() - return True - - def _group_flush(self,group,name): - """Flush a given job group - - Return True if the group had any elements.""" - - njobs = len(group) - if njobs: - plural = {1:''}.setdefault(njobs,'s') - print('Flushing %s %s job%s.' % (njobs,name,plural)) - group[:] = [] - return True - - def _status_new(self): - """Print the status of newly finished jobs. - - Return True if any new jobs are reported. - - This call resets its own state every time, so it only reports jobs - which have finished since the last time it was called.""" - - self._update_status() - new_comp = self._group_report(self._comp_report, 'Completed') - new_dead = self._group_report(self._dead_report, - 'Dead, call jobs.traceback() for details') - self._comp_report[:] = [] - self._dead_report[:] = [] - return new_comp or new_dead - - def status(self,verbose=0): - """Print a status of all jobs currently being managed.""" - - self._update_status() - self._group_report(self.running,'Running') - self._group_report(self.completed,'Completed') - self._group_report(self.dead,'Dead') - # Also flush the report queues - self._comp_report[:] = [] - self._dead_report[:] = [] - - def remove(self,num): - """Remove a finished (completed or dead) job.""" - - try: - job = self.all[num] - except KeyError: - error('Job #%s not found' % num) - else: - stat_code = job.stat_code - if stat_code == self._s_running: - error('Job #%s is still running, it can not be removed.' % num) - return - elif stat_code == self._s_completed: - self.completed.remove(job) - elif stat_code == self._s_dead: - self.dead.remove(job) - - def flush(self): - """Flush all finished jobs (completed and dead) from lists. - - Running jobs are never flushed. - - It first calls _status_new(), to update info. If any jobs have - completed since the last _status_new() call, the flush operation - aborts.""" - - # Remove the finished jobs from the master dict - alljobs = self.all - for job in self.completed+self.dead: - del(alljobs[job.num]) - - # Now flush these lists completely - fl_comp = self._group_flush(self.completed, 'Completed') - fl_dead = self._group_flush(self.dead, 'Dead') - if not (fl_comp or fl_dead): - print('No jobs to flush.') - - def result(self,num): - """result(N) -> return the result of job N.""" - try: - return self.all[num].result - except KeyError: - error('Job #%s not found' % num) - - def _traceback(self, job): - num = job if isinstance(job, int) else job.num - try: - self.all[num].traceback() - except KeyError: - error('Job #%s not found' % num) - - def traceback(self, job=None): - if job is None: - self._update_status() - for deadjob in self.dead: - print("Traceback for: %r" % deadjob) - self._traceback(deadjob) - print() - else: - self._traceback(job) - - -class BackgroundJobBase(threading.Thread): - """Base class to build BackgroundJob classes. - - The derived classes must implement: - - - Their own __init__, since the one here raises NotImplementedError. The - derived constructor must call self._init() at the end, to provide common - initialization. - - - A strform attribute used in calls to __str__. - - - A call() method, which will make the actual execution call and must - return a value to be held in the 'result' field of the job object. - """ - - # Class constants for status, in string and as numerical codes (when - # updating jobs lists, we don't want to do string comparisons). This will - # be done at every user prompt, so it has to be as fast as possible - stat_created = 'Created'; stat_created_c = 0 - stat_running = 'Running'; stat_running_c = 1 - stat_completed = 'Completed'; stat_completed_c = 2 - stat_dead = 'Dead (Exception), call jobs.traceback() for details' - stat_dead_c = -1 - - def __init__(self): - """Must be implemented in subclasses. - - Subclasses must call :meth:`_init` for standard initialisation. - """ - raise NotImplementedError("This class can not be instantiated directly.") - - def _init(self): - """Common initialization for all BackgroundJob objects""" - - for attr in ['call','strform']: - assert hasattr(self,attr), "Missing attribute <%s>" % attr - - # The num tag can be set by an external job manager - self.num = None - - self.status = BackgroundJobBase.stat_created - self.stat_code = BackgroundJobBase.stat_created_c - self.finished = False - self.result = '<BackgroundJob has not completed>' - - # reuse the ipython traceback handler if we can get to it, otherwise - # make a new one - try: - make_tb = get_ipython().InteractiveTB.text - except: - make_tb = AutoFormattedTB(mode = 'Context', - color_scheme='NoColor', - tb_offset = 1).text - # Note that the actual API for text() requires the three args to be - # passed in, so we wrap it in a simple lambda. - self._make_tb = lambda : make_tb(None, None, None) - - # Hold a formatted traceback if one is generated. - self._tb = None - - threading.Thread.__init__(self) - - def __str__(self): - return self.strform - - def __repr__(self): - return '<BackgroundJob #%d: %s>' % (self.num, self.strform) - - def traceback(self): - print(self._tb) - - def run(self): - try: - self.status = BackgroundJobBase.stat_running - self.stat_code = BackgroundJobBase.stat_running_c - self.result = self.call() - except: - self.status = BackgroundJobBase.stat_dead - self.stat_code = BackgroundJobBase.stat_dead_c - self.finished = None - self.result = ('<BackgroundJob died, call jobs.traceback() for details>') - self._tb = self._make_tb() - else: - self.status = BackgroundJobBase.stat_completed - self.stat_code = BackgroundJobBase.stat_completed_c - self.finished = True - - -class BackgroundJobExpr(BackgroundJobBase): - """Evaluate an expression as a background job (uses a separate thread).""" - - def __init__(self, expression, glob=None, loc=None): - """Create a new job from a string which can be fed to eval(). - - global/locals dicts can be provided, which will be passed to the eval - call.""" - - # fail immediately if the given expression can't be compiled - self.code = compile(expression,'<BackgroundJob compilation>','eval') - - glob = {} if glob is None else glob - loc = {} if loc is None else loc - self.expression = self.strform = expression - self.glob = glob - self.loc = loc - self._init() - - def call(self): - return eval(self.code,self.glob,self.loc) - - -class BackgroundJobFunc(BackgroundJobBase): - """Run a function call as a background job (uses a separate thread).""" - - def __init__(self, func, *args, **kwargs): - """Create a new job from a callable object. - - Any positional arguments and keyword args given to this constructor - after the initial callable are passed directly to it.""" - - if not callable(func): - raise TypeError( - 'first argument to BackgroundJobFunc must be callable') - - self.func = func - self.args = args - self.kwargs = kwargs - # The string form will only include the function passed, because - # generating string representations of the arguments is a potentially - # _very_ expensive operation (e.g. with large arrays). - self.strform = str(func) - self._init() - - def call(self): - return self.func(*self.args, **self.kwargs) diff --git a/contrib/python/ipython/py3/IPython/lib/clipboard.py b/contrib/python/ipython/py3/IPython/lib/clipboard.py deleted file mode 100644 index 95a6b0a0a3..0000000000 --- a/contrib/python/ipython/py3/IPython/lib/clipboard.py +++ /dev/null @@ -1,69 +0,0 @@ -""" Utilities for accessing the platform's clipboard. -""" - -import subprocess - -from IPython.core.error import TryNext -import IPython.utils.py3compat as py3compat - -class ClipboardEmpty(ValueError): - pass - -def win32_clipboard_get(): - """ Get the current clipboard's text on Windows. - - Requires Mark Hammond's pywin32 extensions. - """ - try: - import win32clipboard - except ImportError as e: - raise TryNext("Getting text from the clipboard requires the pywin32 " - "extensions: http://sourceforge.net/projects/pywin32/") from e - win32clipboard.OpenClipboard() - try: - text = win32clipboard.GetClipboardData(win32clipboard.CF_UNICODETEXT) - except (TypeError, win32clipboard.error): - try: - text = win32clipboard.GetClipboardData(win32clipboard.CF_TEXT) - text = py3compat.cast_unicode(text, py3compat.DEFAULT_ENCODING) - except (TypeError, win32clipboard.error) as e: - raise ClipboardEmpty from e - finally: - win32clipboard.CloseClipboard() - return text - -def osx_clipboard_get() -> str: - """ Get the clipboard's text on OS X. - """ - p = subprocess.Popen(['pbpaste', '-Prefer', 'ascii'], - stdout=subprocess.PIPE) - bytes_, stderr = p.communicate() - # Text comes in with old Mac \r line endings. Change them to \n. - bytes_ = bytes_.replace(b'\r', b'\n') - text = py3compat.decode(bytes_) - return text - -def tkinter_clipboard_get(): - """ Get the clipboard's text using Tkinter. - - This is the default on systems that are not Windows or OS X. It may - interfere with other UI toolkits and should be replaced with an - implementation that uses that toolkit. - """ - try: - from tkinter import Tk, TclError - except ImportError as e: - raise TryNext("Getting text from the clipboard on this platform requires tkinter.") from e - - root = Tk() - root.withdraw() - try: - text = root.clipboard_get() - except TclError as e: - raise ClipboardEmpty from e - finally: - root.destroy() - text = py3compat.cast_unicode(text, py3compat.DEFAULT_ENCODING) - return text - - diff --git a/contrib/python/ipython/py3/IPython/lib/deepreload.py b/contrib/python/ipython/py3/IPython/lib/deepreload.py deleted file mode 100644 index aaedab2425..0000000000 --- a/contrib/python/ipython/py3/IPython/lib/deepreload.py +++ /dev/null @@ -1,310 +0,0 @@ -# -*- coding: utf-8 -*- -""" -Provides a reload() function that acts recursively. - -Python's normal :func:`python:reload` function only reloads the module that it's -passed. The :func:`reload` function in this module also reloads everything -imported from that module, which is useful when you're changing files deep -inside a package. - -To use this as your default reload function, type this:: - - import builtins - from IPython.lib import deepreload - builtins.reload = deepreload.reload - -A reference to the original :func:`python:reload` is stored in this module as -:data:`original_reload`, so you can restore it later. - -This code is almost entirely based on knee.py, which is a Python -re-implementation of hierarchical module import. -""" -#***************************************************************************** -# Copyright (C) 2001 Nathaniel Gray <n8gray@caltech.edu> -# -# Distributed under the terms of the BSD License. The full license is in -# the file COPYING, distributed as part of this software. -#***************************************************************************** - -import builtins as builtin_mod -from contextlib import contextmanager -import importlib -import sys - -from types import ModuleType -from warnings import warn -import types - -original_import = builtin_mod.__import__ - -@contextmanager -def replace_import_hook(new_import): - saved_import = builtin_mod.__import__ - builtin_mod.__import__ = new_import - try: - yield - finally: - builtin_mod.__import__ = saved_import - -def get_parent(globals, level): - """ - parent, name = get_parent(globals, level) - - Return the package that an import is being performed in. If globals comes - from the module foo.bar.bat (not itself a package), this returns the - sys.modules entry for foo.bar. If globals is from a package's __init__.py, - the package's entry in sys.modules is returned. - - If globals doesn't come from a package or a module in a package, or a - corresponding entry is not found in sys.modules, None is returned. - """ - orig_level = level - - if not level or not isinstance(globals, dict): - return None, '' - - pkgname = globals.get('__package__', None) - - if pkgname is not None: - # __package__ is set, so use it - if not hasattr(pkgname, 'rindex'): - raise ValueError('__package__ set to non-string') - if len(pkgname) == 0: - if level > 0: - raise ValueError('Attempted relative import in non-package') - return None, '' - name = pkgname - else: - # __package__ not set, so figure it out and set it - if '__name__' not in globals: - return None, '' - modname = globals['__name__'] - - if '__path__' in globals: - # __path__ is set, so modname is already the package name - globals['__package__'] = name = modname - else: - # Normal module, so work out the package name if any - lastdot = modname.rfind('.') - if lastdot < 0 < level: - raise ValueError("Attempted relative import in non-package") - if lastdot < 0: - globals['__package__'] = None - return None, '' - globals['__package__'] = name = modname[:lastdot] - - dot = len(name) - for x in range(level, 1, -1): - try: - dot = name.rindex('.', 0, dot) - except ValueError as e: - raise ValueError("attempted relative import beyond top-level " - "package") from e - name = name[:dot] - - try: - parent = sys.modules[name] - except BaseException as e: - if orig_level < 1: - warn("Parent module '%.200s' not found while handling absolute " - "import" % name) - parent = None - else: - raise SystemError("Parent module '%.200s' not loaded, cannot " - "perform relative import" % name) from e - - # We expect, but can't guarantee, if parent != None, that: - # - parent.__name__ == name - # - parent.__dict__ is globals - # If this is violated... Who cares? - return parent, name - -def load_next(mod, altmod, name, buf): - """ - mod, name, buf = load_next(mod, altmod, name, buf) - - altmod is either None or same as mod - """ - - if len(name) == 0: - # completely empty module name should only happen in - # 'from . import' (or '__import__("")') - return mod, None, buf - - dot = name.find('.') - if dot == 0: - raise ValueError('Empty module name') - - if dot < 0: - subname = name - next = None - else: - subname = name[:dot] - next = name[dot+1:] - - if buf != '': - buf += '.' - buf += subname - - result = import_submodule(mod, subname, buf) - if result is None and mod != altmod: - result = import_submodule(altmod, subname, subname) - if result is not None: - buf = subname - - if result is None: - raise ImportError("No module named %.200s" % name) - - return result, next, buf - - -# Need to keep track of what we've already reloaded to prevent cyclic evil -found_now = {} - -def import_submodule(mod, subname, fullname): - """m = import_submodule(mod, subname, fullname)""" - # Require: - # if mod == None: subname == fullname - # else: mod.__name__ + "." + subname == fullname - - global found_now - if fullname in found_now and fullname in sys.modules: - m = sys.modules[fullname] - else: - print('Reloading', fullname) - found_now[fullname] = 1 - oldm = sys.modules.get(fullname, None) - try: - if oldm is not None: - m = importlib.reload(oldm) - else: - m = importlib.import_module(subname, mod) - except: - # load_module probably removed name from modules because of - # the error. Put back the original module object. - if oldm: - sys.modules[fullname] = oldm - raise - - add_submodule(mod, m, fullname, subname) - - return m - -def add_submodule(mod, submod, fullname, subname): - """mod.{subname} = submod""" - if mod is None: - return #Nothing to do here. - - if submod is None: - submod = sys.modules[fullname] - - setattr(mod, subname, submod) - - return - -def ensure_fromlist(mod, fromlist, buf, recursive): - """Handle 'from module import a, b, c' imports.""" - if not hasattr(mod, '__path__'): - return - for item in fromlist: - if not hasattr(item, 'rindex'): - raise TypeError("Item in ``from list'' not a string") - if item == '*': - if recursive: - continue # avoid endless recursion - try: - all = mod.__all__ - except AttributeError: - pass - else: - ret = ensure_fromlist(mod, all, buf, 1) - if not ret: - return 0 - elif not hasattr(mod, item): - import_submodule(mod, item, buf + '.' + item) - -def deep_import_hook(name, globals=None, locals=None, fromlist=None, level=-1): - """Replacement for __import__()""" - parent, buf = get_parent(globals, level) - - head, name, buf = load_next(parent, None if level < 0 else parent, name, buf) - - tail = head - while name: - tail, name, buf = load_next(tail, tail, name, buf) - - # If tail is None, both get_parent and load_next found - # an empty module name: someone called __import__("") or - # doctored faulty bytecode - if tail is None: - raise ValueError('Empty module name') - - if not fromlist: - return head - - ensure_fromlist(tail, fromlist, buf, 0) - return tail - -modules_reloading = {} - -def deep_reload_hook(m): - """Replacement for reload().""" - # Hardcode this one as it would raise a NotImplementedError from the - # bowels of Python and screw up the import machinery after. - # unlike other imports the `exclude` list already in place is not enough. - - if m is types: - return m - if not isinstance(m, ModuleType): - raise TypeError("reload() argument must be module") - - name = m.__name__ - - if name not in sys.modules: - raise ImportError("reload(): module %.200s not in sys.modules" % name) - - global modules_reloading - try: - return modules_reloading[name] - except: - modules_reloading[name] = m - - try: - newm = importlib.reload(m) - except: - sys.modules[name] = m - raise - finally: - modules_reloading.clear() - return newm - -# Save the original hooks -original_reload = importlib.reload - -# Replacement for reload() -def reload( - module, - exclude=( - *sys.builtin_module_names, - "sys", - "os.path", - "builtins", - "__main__", - "numpy", - "numpy._globals", - ), -): - """Recursively reload all modules used in the given module. Optionally - takes a list of modules to exclude from reloading. The default exclude - list contains modules listed in sys.builtin_module_names with additional - sys, os.path, builtins and __main__, to prevent, e.g., resetting - display, exception, and io hooks. - """ - global found_now - for i in exclude: - found_now[i] = 1 - try: - with replace_import_hook(deep_import_hook): - return deep_reload_hook(module) - finally: - found_now = {} diff --git a/contrib/python/ipython/py3/IPython/lib/demo.py b/contrib/python/ipython/py3/IPython/lib/demo.py deleted file mode 100644 index 8c9ae905d4..0000000000 --- a/contrib/python/ipython/py3/IPython/lib/demo.py +++ /dev/null @@ -1,672 +0,0 @@ -"""Module for interactive demos using IPython. - -This module implements a few classes for running Python scripts interactively -in IPython for demonstrations. With very simple markup (a few tags in -comments), you can control points where the script stops executing and returns -control to IPython. - - -Provided classes ----------------- - -The classes are (see their docstrings for further details): - - - Demo: pure python demos - - - IPythonDemo: demos with input to be processed by IPython as if it had been - typed interactively (so magics work, as well as any other special syntax you - may have added via input prefilters). - - - LineDemo: single-line version of the Demo class. These demos are executed - one line at a time, and require no markup. - - - IPythonLineDemo: IPython version of the LineDemo class (the demo is - executed a line at a time, but processed via IPython). - - - ClearMixin: mixin to make Demo classes with less visual clutter. It - declares an empty marquee and a pre_cmd that clears the screen before each - block (see Subclassing below). - - - ClearDemo, ClearIPDemo: mixin-enabled versions of the Demo and IPythonDemo - classes. - -Inheritance diagram: - -.. inheritance-diagram:: IPython.lib.demo - :parts: 3 - -Subclassing ------------ - -The classes here all include a few methods meant to make customization by -subclassing more convenient. Their docstrings below have some more details: - - - highlight(): format every block and optionally highlight comments and - docstring content. - - - marquee(): generates a marquee to provide visible on-screen markers at each - block start and end. - - - pre_cmd(): run right before the execution of each block. - - - post_cmd(): run right after the execution of each block. If the block - raises an exception, this is NOT called. - - -Operation ---------- - -The file is run in its own empty namespace (though you can pass it a string of -arguments as if in a command line environment, and it will see those as -sys.argv). But at each stop, the global IPython namespace is updated with the -current internal demo namespace, so you can work interactively with the data -accumulated so far. - -By default, each block of code is printed (with syntax highlighting) before -executing it and you have to confirm execution. This is intended to show the -code to an audience first so you can discuss it, and only proceed with -execution once you agree. There are a few tags which allow you to modify this -behavior. - -The supported tags are: - -# <demo> stop - - Defines block boundaries, the points where IPython stops execution of the - file and returns to the interactive prompt. - - You can optionally mark the stop tag with extra dashes before and after the - word 'stop', to help visually distinguish the blocks in a text editor: - - # <demo> --- stop --- - - -# <demo> silent - - Make a block execute silently (and hence automatically). Typically used in - cases where you have some boilerplate or initialization code which you need - executed but do not want to be seen in the demo. - -# <demo> auto - - Make a block execute automatically, but still being printed. Useful for - simple code which does not warrant discussion, since it avoids the extra - manual confirmation. - -# <demo> auto_all - - This tag can _only_ be in the first block, and if given it overrides the - individual auto tags to make the whole demo fully automatic (no block asks - for confirmation). It can also be given at creation time (or the attribute - set later) to override what's in the file. - -While _any_ python file can be run as a Demo instance, if there are no stop -tags the whole file will run in a single block (no different that calling -first %pycat and then %run). The minimal markup to make this useful is to -place a set of stop tags; the other tags are only there to let you fine-tune -the execution. - -This is probably best explained with the simple example file below. You can -copy this into a file named ex_demo.py, and try running it via:: - - from IPython.lib.demo import Demo - d = Demo('ex_demo.py') - d() - -Each time you call the demo object, it runs the next block. The demo object -has a few useful methods for navigation, like again(), edit(), jump(), seek() -and back(). It can be reset for a new run via reset() or reloaded from disk -(in case you've edited the source) via reload(). See their docstrings below. - -Note: To make this simpler to explore, a file called "demo-exercizer.py" has -been added to the "docs/examples/core" directory. Just cd to this directory in -an IPython session, and type:: - - %run demo-exercizer.py - -and then follow the directions. - -Example -------- - -The following is a very simple example of a valid demo file. - -:: - - #################### EXAMPLE DEMO <ex_demo.py> ############################### - '''A simple interactive demo to illustrate the use of IPython's Demo class.''' - - print 'Hello, welcome to an interactive IPython demo.' - - # The mark below defines a block boundary, which is a point where IPython will - # stop execution and return to the interactive prompt. The dashes are actually - # optional and used only as a visual aid to clearly separate blocks while - # editing the demo code. - # <demo> stop - - x = 1 - y = 2 - - # <demo> stop - - # the mark below makes this block as silent - # <demo> silent - - print 'This is a silent block, which gets executed but not printed.' - - # <demo> stop - # <demo> auto - print 'This is an automatic block.' - print 'It is executed without asking for confirmation, but printed.' - z = x+y - - print 'z=',x - - # <demo> stop - # This is just another normal block. - print 'z is now:', z - - print 'bye!' - ################### END EXAMPLE DEMO <ex_demo.py> ############################ -""" - - -#***************************************************************************** -# Copyright (C) 2005-2006 Fernando Perez. <Fernando.Perez@colorado.edu> -# -# Distributed under the terms of the BSD License. The full license is in -# the file COPYING, distributed as part of this software. -# -#***************************************************************************** - -import os -import re -import shlex -import sys -import pygments -from pathlib import Path - -from IPython.utils.text import marquee -from IPython.utils import openpy -from IPython.utils import py3compat -__all__ = ['Demo','IPythonDemo','LineDemo','IPythonLineDemo','DemoError'] - -class DemoError(Exception): pass - -def re_mark(mark): - return re.compile(r'^\s*#\s+<demo>\s+%s\s*$' % mark,re.MULTILINE) - -class Demo(object): - - re_stop = re_mark(r'-*\s?stop\s?-*') - re_silent = re_mark('silent') - re_auto = re_mark('auto') - re_auto_all = re_mark('auto_all') - - def __init__(self,src,title='',arg_str='',auto_all=None, format_rst=False, - formatter='terminal', style='default'): - """Make a new demo object. To run the demo, simply call the object. - - See the module docstring for full details and an example (you can use - IPython.Demo? in IPython to see it). - - Inputs: - - - src is either a file, or file-like object, or a - string that can be resolved to a filename. - - Optional inputs: - - - title: a string to use as the demo name. Of most use when the demo - you are making comes from an object that has no filename, or if you - want an alternate denotation distinct from the filename. - - - arg_str(''): a string of arguments, internally converted to a list - just like sys.argv, so the demo script can see a similar - environment. - - - auto_all(None): global flag to run all blocks automatically without - confirmation. This attribute overrides the block-level tags and - applies to the whole demo. It is an attribute of the object, and - can be changed at runtime simply by reassigning it to a boolean - value. - - - format_rst(False): a bool to enable comments and doc strings - formatting with pygments rst lexer - - - formatter('terminal'): a string of pygments formatter name to be - used. Useful values for terminals: terminal, terminal256, - terminal16m - - - style('default'): a string of pygments style name to be used. - """ - if hasattr(src, "read"): - # It seems to be a file or a file-like object - self.fname = "from a file-like object" - if title == '': - self.title = "from a file-like object" - else: - self.title = title - else: - # Assume it's a string or something that can be converted to one - self.fname = src - if title == '': - (filepath, filename) = os.path.split(src) - self.title = filename - else: - self.title = title - self.sys_argv = [src] + shlex.split(arg_str) - self.auto_all = auto_all - self.src = src - - try: - ip = get_ipython() # this is in builtins whenever IPython is running - self.inside_ipython = True - except NameError: - self.inside_ipython = False - - if self.inside_ipython: - # get a few things from ipython. While it's a bit ugly design-wise, - # it ensures that things like color scheme and the like are always in - # sync with the ipython mode being used. This class is only meant to - # be used inside ipython anyways, so it's OK. - self.ip_ns = ip.user_ns - self.ip_colorize = ip.pycolorize - self.ip_showtb = ip.showtraceback - self.ip_run_cell = ip.run_cell - self.shell = ip - - self.formatter = pygments.formatters.get_formatter_by_name(formatter, - style=style) - self.python_lexer = pygments.lexers.get_lexer_by_name("py3") - self.format_rst = format_rst - if format_rst: - self.rst_lexer = pygments.lexers.get_lexer_by_name("rst") - - # load user data and initialize data structures - self.reload() - - def fload(self): - """Load file object.""" - # read data and parse into blocks - if hasattr(self, 'fobj') and self.fobj is not None: - self.fobj.close() - if hasattr(self.src, "read"): - # It seems to be a file or a file-like object - self.fobj = self.src - else: - # Assume it's a string or something that can be converted to one - self.fobj = openpy.open(self.fname) - - def reload(self): - """Reload source from disk and initialize state.""" - self.fload() - - self.src = "".join(openpy.strip_encoding_cookie(self.fobj)) - src_b = [b.strip() for b in self.re_stop.split(self.src) if b] - self._silent = [bool(self.re_silent.findall(b)) for b in src_b] - self._auto = [bool(self.re_auto.findall(b)) for b in src_b] - - # if auto_all is not given (def. None), we read it from the file - if self.auto_all is None: - self.auto_all = bool(self.re_auto_all.findall(src_b[0])) - else: - self.auto_all = bool(self.auto_all) - - # Clean the sources from all markup so it doesn't get displayed when - # running the demo - src_blocks = [] - auto_strip = lambda s: self.re_auto.sub('',s) - for i,b in enumerate(src_b): - if self._auto[i]: - src_blocks.append(auto_strip(b)) - else: - src_blocks.append(b) - # remove the auto_all marker - src_blocks[0] = self.re_auto_all.sub('',src_blocks[0]) - - self.nblocks = len(src_blocks) - self.src_blocks = src_blocks - - # also build syntax-highlighted source - self.src_blocks_colored = list(map(self.highlight,self.src_blocks)) - - # ensure clean namespace and seek offset - self.reset() - - def reset(self): - """Reset the namespace and seek pointer to restart the demo""" - self.user_ns = {} - self.finished = False - self.block_index = 0 - - def _validate_index(self,index): - if index<0 or index>=self.nblocks: - raise ValueError('invalid block index %s' % index) - - def _get_index(self,index): - """Get the current block index, validating and checking status. - - Returns None if the demo is finished""" - - if index is None: - if self.finished: - print('Demo finished. Use <demo_name>.reset() if you want to rerun it.') - return None - index = self.block_index - else: - self._validate_index(index) - return index - - def seek(self,index): - """Move the current seek pointer to the given block. - - You can use negative indices to seek from the end, with identical - semantics to those of Python lists.""" - if index<0: - index = self.nblocks + index - self._validate_index(index) - self.block_index = index - self.finished = False - - def back(self,num=1): - """Move the seek pointer back num blocks (default is 1).""" - self.seek(self.block_index-num) - - def jump(self,num=1): - """Jump a given number of blocks relative to the current one. - - The offset can be positive or negative, defaults to 1.""" - self.seek(self.block_index+num) - - def again(self): - """Move the seek pointer back one block and re-execute.""" - self.back(1) - self() - - def edit(self,index=None): - """Edit a block. - - If no number is given, use the last block executed. - - This edits the in-memory copy of the demo, it does NOT modify the - original source file. If you want to do that, simply open the file in - an editor and use reload() when you make changes to the file. This - method is meant to let you change a block during a demonstration for - explanatory purposes, without damaging your original script.""" - - index = self._get_index(index) - if index is None: - return - # decrease the index by one (unless we're at the very beginning), so - # that the default demo.edit() call opens up the sblock we've last run - if index>0: - index -= 1 - - filename = self.shell.mktempfile(self.src_blocks[index]) - self.shell.hooks.editor(filename, 1) - with open(Path(filename), "r", encoding="utf-8") as f: - new_block = f.read() - # update the source and colored block - self.src_blocks[index] = new_block - self.src_blocks_colored[index] = self.highlight(new_block) - self.block_index = index - # call to run with the newly edited index - self() - - def show(self,index=None): - """Show a single block on screen""" - - index = self._get_index(index) - if index is None: - return - - print(self.marquee('<%s> block # %s (%s remaining)' % - (self.title,index,self.nblocks-index-1))) - print(self.src_blocks_colored[index]) - sys.stdout.flush() - - def show_all(self): - """Show entire demo on screen, block by block""" - - fname = self.title - title = self.title - nblocks = self.nblocks - silent = self._silent - marquee = self.marquee - 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))) - else: - print(marquee('<%s> block # %s (%s remaining)' % - (title,index,nblocks-index-1))) - print(block, end=' ') - sys.stdout.flush() - - def run_cell(self,source): - """Execute a string with one or more lines of code""" - - exec(source, self.user_ns) - - def __call__(self,index=None): - """run a block of the demo. - - If index is given, it should be an integer >=1 and <= nblocks. This - means that the calling convention is one off from typical Python - lists. The reason for the inconsistency is that the demo always - prints 'Block n/N, and N is the total, so it would be very odd to use - zero-indexing here.""" - - index = self._get_index(index) - if index is None: - return - try: - marquee = self.marquee - next_block = self.src_blocks[index] - self.block_index += 1 - if self._silent[index]: - print(marquee('Executing silent block # %s (%s remaining)' % - (index,self.nblocks-index-1))) - else: - self.pre_cmd() - self.show(index) - if self.auto_all or self._auto[index]: - print(marquee('output:')) - else: - print(marquee('Press <q> to quit, <Enter> to execute...'), end=' ') - ans = py3compat.input().strip() - if ans: - print(marquee('Block NOT executed')) - return - try: - save_argv = sys.argv - sys.argv = self.sys_argv - self.run_cell(next_block) - self.post_cmd() - finally: - sys.argv = save_argv - - except: - if self.inside_ipython: - self.ip_showtb(filename=self.fname) - else: - if self.inside_ipython: - self.ip_ns.update(self.user_ns) - - 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.')) - self.finished = True - - # These methods are meant to be overridden by subclasses who may wish to - # customize the behavior of of their demos. - def marquee(self,txt='',width=78,mark='*'): - """Return the input string centered in a 'marquee'.""" - return marquee(txt,width,mark) - - def pre_cmd(self): - """Method called before executing each block.""" - pass - - def post_cmd(self): - """Method called after executing each block.""" - pass - - def highlight(self, block): - """Method called on each block to highlight it content""" - tokens = pygments.lex(block, self.python_lexer) - if self.format_rst: - from pygments.token import Token - toks = [] - for token in tokens: - if token[0] == Token.String.Doc and len(token[1]) > 6: - toks += pygments.lex(token[1][:3], self.python_lexer) - # parse doc string content by rst lexer - toks += pygments.lex(token[1][3:-3], self.rst_lexer) - toks += pygments.lex(token[1][-3:], self.python_lexer) - elif token[0] == Token.Comment.Single: - toks.append((Token.Comment.Single, token[1][0])) - # parse comment content by rst lexer - # remove the extra newline added by rst lexer - toks += list(pygments.lex(token[1][1:], self.rst_lexer))[:-1] - else: - toks.append(token) - tokens = toks - return pygments.format(tokens, self.formatter) - - -class IPythonDemo(Demo): - """Class for interactive demos with IPython's input processing applied. - - This subclasses Demo, but instead of executing each block by the Python - interpreter (via exec), it actually calls IPython on it, so that any input - filters which may be in place are applied to the input block. - - If you have an interactive environment which exposes special input - processing, you can use this class instead to write demo scripts which - operate exactly as if you had typed them interactively. The default Demo - class requires the input to be valid, pure Python code. - """ - - def run_cell(self,source): - """Execute a string with one or more lines of code""" - - self.shell.run_cell(source) - -class LineDemo(Demo): - """Demo where each line is executed as a separate block. - - The input script should be valid Python code. - - This class doesn't require any markup at all, and it's meant for simple - scripts (with no nesting or any kind of indentation) which consist of - multiple lines of input to be executed, one at a time, as if they had been - typed in the interactive prompt. - - Note: the input can not have *any* indentation, which means that only - single-lines of input are accepted, not even function definitions are - valid.""" - - def reload(self): - """Reload source from disk and initialize state.""" - # read data and parse into blocks - self.fload() - lines = self.fobj.readlines() - src_b = [l for l in lines if l.strip()] - nblocks = len(src_b) - self.src = ''.join(lines) - self._silent = [False]*nblocks - self._auto = [True]*nblocks - self.auto_all = True - self.nblocks = nblocks - self.src_blocks = src_b - - # also build syntax-highlighted source - self.src_blocks_colored = list(map(self.highlight,self.src_blocks)) - - # ensure clean namespace and seek offset - self.reset() - - -class IPythonLineDemo(IPythonDemo,LineDemo): - """Variant of the LineDemo class whose input is processed by IPython.""" - pass - - -class ClearMixin(object): - """Use this mixin to make Demo classes with less visual clutter. - - Demos using this mixin will clear the screen before every block and use - blank marquees. - - Note that in order for the methods defined here to actually override those - of the classes it's mixed with, it must go /first/ in the inheritance - tree. For example: - - class ClearIPDemo(ClearMixin,IPythonDemo): pass - - will provide an IPythonDemo class with the mixin's features. - """ - - def marquee(self,txt='',width=78,mark='*'): - """Blank marquee that returns '' no matter what the input.""" - return '' - - def pre_cmd(self): - """Method called before executing each block. - - This one simply clears the screen.""" - from IPython.utils.terminal import _term_clear - _term_clear() - -class ClearDemo(ClearMixin,Demo): - pass - - -class ClearIPDemo(ClearMixin,IPythonDemo): - pass - - -def slide(file_path, noclear=False, format_rst=True, formatter="terminal", - style="native", auto_all=False, delimiter='...'): - if noclear: - demo_class = Demo - else: - demo_class = ClearDemo - demo = demo_class(file_path, format_rst=format_rst, formatter=formatter, - style=style, auto_all=auto_all) - while not demo.finished: - demo() - try: - py3compat.input('\n' + delimiter) - except KeyboardInterrupt: - exit(1) - -if __name__ == '__main__': - import argparse - parser = argparse.ArgumentParser(description='Run python demos') - parser.add_argument('--noclear', '-C', action='store_true', - help='Do not clear terminal on each slide') - parser.add_argument('--rst', '-r', action='store_true', - help='Highlight comments and dostrings as rst') - parser.add_argument('--formatter', '-f', default='terminal', - help='pygments formatter name could be: terminal, ' - 'terminal256, terminal16m') - parser.add_argument('--style', '-s', default='default', - help='pygments style name') - parser.add_argument('--auto', '-a', action='store_true', - help='Run all blocks automatically without' - 'confirmation') - parser.add_argument('--delimiter', '-d', default='...', - help='slides delimiter added after each slide run') - parser.add_argument('file', nargs=1, - help='python demo file') - args = parser.parse_args() - slide(args.file[0], noclear=args.noclear, format_rst=args.rst, - formatter=args.formatter, style=args.style, auto_all=args.auto, - delimiter=args.delimiter) diff --git a/contrib/python/ipython/py3/IPython/lib/display.py b/contrib/python/ipython/py3/IPython/lib/display.py deleted file mode 100644 index 5ff2983dbf..0000000000 --- a/contrib/python/ipython/py3/IPython/lib/display.py +++ /dev/null @@ -1,675 +0,0 @@ -"""Various display related classes. - -Authors : MinRK, gregcaporaso, dannystaple -""" -from html import escape as html_escape -from os.path import exists, isfile, splitext, abspath, join, isdir -from os import walk, sep, fsdecode - -from IPython.core.display import DisplayObject, TextDisplayObject - -from typing import Tuple, Iterable - -__all__ = ['Audio', 'IFrame', 'YouTubeVideo', 'VimeoVideo', 'ScribdDocument', - 'FileLink', 'FileLinks', 'Code'] - - -class Audio(DisplayObject): - """Create an audio object. - - When this object is returned by an input cell or passed to the - display function, it will result in Audio controls being displayed - in the frontend (only works in the notebook). - - Parameters - ---------- - data : numpy array, list, unicode, str or bytes - Can be one of - - * Numpy 1d array containing the desired waveform (mono) - * Numpy 2d array containing waveforms for each channel. - Shape=(NCHAN, NSAMPLES). For the standard channel order, see - http://msdn.microsoft.com/en-us/library/windows/hardware/dn653308(v=vs.85).aspx - * List of float or integer representing the waveform (mono) - * String containing the filename - * Bytestring containing raw PCM data or - * URL pointing to a file on the web. - - If the array option is used, the waveform will be normalized. - - If a filename or url is used, the format support will be browser - dependent. - url : unicode - A URL to download the data from. - 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 - the original source be referenced. Set this to True if you want the - audio to playable later with no internet connection in the notebook. - - Default is `True`, unless the keyword argument `url` is set, then - default value is `False`. - rate : integer - The sampling rate of the raw data. - Only required when data parameter is being used as an array - autoplay : bool - Set to True if the audio should immediately start playing. - Default is `False`. - normalize : bool - Whether audio should be normalized (rescaled) to the maximum possible - range. Default is `True`. When set to `False`, `data` must be between - -1 and 1 (inclusive), otherwise an error is raised. - Applies only when `data` is a list or array of samples; other types of - audio are never normalized. - - Examples - -------- - - >>> import pytest - >>> np = pytest.importorskip("numpy") - - Generate a sound - - >>> import numpy as np - >>> framerate = 44100 - >>> t = np.linspace(0,5,framerate*5) - >>> data = np.sin(2*np.pi*220*t) + np.sin(2*np.pi*224*t) - >>> Audio(data, rate=framerate) - <IPython.lib.display.Audio object> - - Can also do stereo or more channels - - >>> dataleft = np.sin(2*np.pi*220*t) - >>> dataright = np.sin(2*np.pi*224*t) - >>> Audio([dataleft, dataright], rate=framerate) - <IPython.lib.display.Audio object> - - From URL: - - >>> Audio("http://www.nch.com.au/acm/8k16bitpcm.wav") # doctest: +SKIP - >>> Audio(url="http://www.w3schools.com/html/horse.ogg") # doctest: +SKIP - - From a File: - - >>> Audio('IPython/lib/tests/test.wav') # doctest: +SKIP - >>> Audio(filename='IPython/lib/tests/test.wav') # doctest: +SKIP - - From Bytes: - - >>> Audio(b'RAW_WAV_DATA..') # doctest: +SKIP - >>> Audio(data=b'RAW_WAV_DATA..') # doctest: +SKIP - - See Also - -------- - ipywidgets.Audio - - Audio widget with more more flexibility and options. - - """ - _read_flags = 'rb' - - def __init__(self, data=None, filename=None, url=None, embed=None, rate=None, autoplay=False, normalize=True, *, - element_id=None): - if filename is None and url is None and data is None: - raise ValueError("No audio data found. Expecting filename, url, or data.") - if embed is False and url is None: - raise ValueError("No url found. Expecting url when embed=False") - - if url is not None and embed is not True: - self.embed = False - else: - self.embed = True - self.autoplay = autoplay - self.element_id = element_id - super(Audio, self).__init__(data=data, url=url, filename=filename) - - if self.data is not None and not isinstance(self.data, bytes): - if rate is None: - raise ValueError("rate must be specified when data is a numpy array or list of audio samples.") - self.data = Audio._make_wav(data, rate, normalize) - - def reload(self): - """Reload the raw data from file or URL.""" - import mimetypes - if self.embed: - super(Audio, self).reload() - - if self.filename is not None: - self.mimetype = mimetypes.guess_type(self.filename)[0] - elif self.url is not None: - self.mimetype = mimetypes.guess_type(self.url)[0] - else: - self.mimetype = "audio/wav" - - @staticmethod - def _make_wav(data, rate, normalize): - """ Transform a numpy array to a PCM bytestring """ - from io import BytesIO - import wave - - try: - scaled, nchan = Audio._validate_and_normalize_with_numpy(data, normalize) - except ImportError: - scaled, nchan = Audio._validate_and_normalize_without_numpy(data, normalize) - - fp = BytesIO() - waveobj = wave.open(fp,mode='wb') - waveobj.setnchannels(nchan) - waveobj.setframerate(rate) - waveobj.setsampwidth(2) - waveobj.setcomptype('NONE','NONE') - waveobj.writeframes(scaled) - val = fp.getvalue() - waveobj.close() - - return val - - @staticmethod - def _validate_and_normalize_with_numpy(data, normalize) -> Tuple[bytes, int]: - import numpy as np - - data = np.array(data, dtype=float) - if len(data.shape) == 1: - nchan = 1 - elif len(data.shape) == 2: - # In wave files,channels are interleaved. E.g., - # "L1R1L2R2..." for stereo. See - # http://msdn.microsoft.com/en-us/library/windows/hardware/dn653308(v=vs.85).aspx - # for channel ordering - nchan = data.shape[0] - data = data.T.ravel() - else: - raise ValueError('Array audio input must be a 1D or 2D array') - - max_abs_value = np.max(np.abs(data)) - normalization_factor = Audio._get_normalization_factor(max_abs_value, normalize) - scaled = data / normalization_factor * 32767 - return scaled.astype("<h").tobytes(), nchan - - @staticmethod - def _validate_and_normalize_without_numpy(data, normalize): - import array - import sys - - data = array.array('f', data) - - try: - max_abs_value = float(max([abs(x) for x in data])) - except TypeError as e: - raise TypeError('Only lists of mono audio are ' - 'supported if numpy is not installed') from e - - normalization_factor = Audio._get_normalization_factor(max_abs_value, normalize) - scaled = array.array('h', [int(x / normalization_factor * 32767) for x in data]) - if sys.byteorder == 'big': - scaled.byteswap() - nchan = 1 - return scaled.tobytes(), nchan - - @staticmethod - def _get_normalization_factor(max_abs_value, normalize): - if not normalize and max_abs_value > 1: - raise ValueError('Audio data must be between -1 and 1 when normalize=False.') - return max_abs_value if normalize else 1 - - def _data_and_metadata(self): - """shortcut for returning metadata with url information, if defined""" - md = {} - if self.url: - md['url'] = self.url - if md: - return self.data, md - else: - return self.data - - def _repr_html_(self): - src = """ - <audio {element_id} controls="controls" {autoplay}> - <source src="{src}" type="{type}" /> - Your browser does not support the audio element. - </audio> - """ - return src.format(src=self.src_attr(), type=self.mimetype, autoplay=self.autoplay_attr(), - element_id=self.element_id_attr()) - - def src_attr(self): - import base64 - if self.embed and (self.data is not None): - data = base64=base64.b64encode(self.data).decode('ascii') - return """data:{type};base64,{base64}""".format(type=self.mimetype, - base64=data) - elif self.url is not None: - return self.url - else: - return "" - - def autoplay_attr(self): - if(self.autoplay): - return 'autoplay="autoplay"' - else: - return '' - - def element_id_attr(self): - if (self.element_id): - return 'id="{element_id}"'.format(element_id=self.element_id) - else: - return '' - -class IFrame(object): - """ - Generic class to embed an iframe in an IPython notebook - """ - - iframe = """ - <iframe - width="{width}" - height="{height}" - src="{src}{params}" - frameborder="0" - allowfullscreen - {extras} - ></iframe> - """ - - def __init__(self, src, width, height, extras: Iterable[str] = None, **kwargs): - if extras is None: - extras = [] - - self.src = src - self.width = width - self.height = height - self.extras = extras - self.params = kwargs - - def _repr_html_(self): - """return the embed iframe""" - if self.params: - from urllib.parse import urlencode - params = "?" + urlencode(self.params) - else: - params = "" - return self.iframe.format( - src=self.src, - width=self.width, - height=self.height, - params=params, - extras=" ".join(self.extras), - ) - - -class YouTubeVideo(IFrame): - """Class for embedding a YouTube Video in an IPython session, based on its video id. - - e.g. to embed the video from https://www.youtube.com/watch?v=foo , you would - do:: - - vid = YouTubeVideo("foo") - display(vid) - - To start from 30 seconds:: - - vid = YouTubeVideo("abc", start=30) - display(vid) - - To calculate seconds from time as hours, minutes, seconds use - :class:`datetime.timedelta`:: - - start=int(timedelta(hours=1, minutes=46, seconds=40).total_seconds()) - - Other parameters can be provided as documented at - https://developers.google.com/youtube/player_parameters#Parameters - - When converting the notebook using nbconvert, a jpeg representation of the video - will be inserted in the document. - """ - - def __init__(self, id, width=400, height=300, allow_autoplay=False, **kwargs): - self.id=id - src = "https://www.youtube.com/embed/{0}".format(id) - if allow_autoplay: - extras = list(kwargs.get("extras", [])) + ['allow="autoplay"'] - kwargs.update(autoplay=1, extras=extras) - super(YouTubeVideo, self).__init__(src, width, height, **kwargs) - - def _repr_jpeg_(self): - # Deferred import - from urllib.request import urlopen - - try: - return urlopen("https://img.youtube.com/vi/{id}/hqdefault.jpg".format(id=self.id)).read() - except IOError: - return None - -class VimeoVideo(IFrame): - """ - Class for embedding a Vimeo video in an IPython session, based on its video id. - """ - - def __init__(self, id, width=400, height=300, **kwargs): - src="https://player.vimeo.com/video/{0}".format(id) - super(VimeoVideo, self).__init__(src, width, height, **kwargs) - -class ScribdDocument(IFrame): - """ - Class for embedding a Scribd document in an IPython session - - Use the start_page params to specify a starting point in the document - Use the view_mode params to specify display type one off scroll | slideshow | book - - e.g to Display Wes' foundational paper about PANDAS in book mode from page 3 - - ScribdDocument(71048089, width=800, height=400, start_page=3, view_mode="book") - """ - - def __init__(self, id, width=400, height=300, **kwargs): - src="https://www.scribd.com/embeds/{0}/content".format(id) - super(ScribdDocument, self).__init__(src, width, height, **kwargs) - -class FileLink(object): - """Class for embedding a local file link in an IPython session, based on path - - e.g. to embed a link that was generated in the IPython notebook as my/data.txt - - you would do:: - - local_file = FileLink("my/data.txt") - display(local_file) - - or in the HTML notebook, just:: - - FileLink("my/data.txt") - """ - - html_link_str = "<a href='%s' target='_blank'>%s</a>" - - def __init__(self, - path, - url_prefix='', - result_html_prefix='', - result_html_suffix='<br>'): - """ - Parameters - ---------- - path : str - path to the file or directory that should be formatted - url_prefix : str - prefix to be prepended to all files to form a working link [default: - ''] - result_html_prefix : str - text to append to beginning to link [default: ''] - result_html_suffix : str - text to append at the end of link [default: '<br>'] - """ - if isdir(path): - raise ValueError("Cannot display a directory using FileLink. " - "Use FileLinks to display '%s'." % path) - self.path = fsdecode(path) - self.url_prefix = url_prefix - self.result_html_prefix = result_html_prefix - self.result_html_suffix = result_html_suffix - - def _format_path(self): - fp = ''.join([self.url_prefix, html_escape(self.path)]) - return ''.join([self.result_html_prefix, - self.html_link_str % \ - (fp, html_escape(self.path, quote=False)), - self.result_html_suffix]) - - def _repr_html_(self): - """return html link to file - """ - if not exists(self.path): - return ("Path (<tt>%s</tt>) doesn't exist. " - "It may still be in the process of " - "being generated, or you may have the " - "incorrect path." % self.path) - - return self._format_path() - - def __repr__(self): - """return absolute path to file - """ - return abspath(self.path) - -class FileLinks(FileLink): - """Class for embedding local file links in an IPython session, based on path - - e.g. to embed links to files that were generated in the IPython notebook - under ``my/data``, you would do:: - - local_files = FileLinks("my/data") - display(local_files) - - or in the HTML notebook, just:: - - FileLinks("my/data") - """ - def __init__(self, - path, - url_prefix='', - included_suffixes=None, - result_html_prefix='', - result_html_suffix='<br>', - notebook_display_formatter=None, - terminal_display_formatter=None, - recursive=True): - """ - See :class:`FileLink` for the ``path``, ``url_prefix``, - ``result_html_prefix`` and ``result_html_suffix`` parameters. - - included_suffixes : list - Filename suffixes to include when formatting output [default: include - all files] - - notebook_display_formatter : function - Used to format links for display in the notebook. See discussion of - formatter functions below. - - terminal_display_formatter : function - Used to format links for display in the terminal. See discussion of - formatter functions below. - - Formatter functions must be of the form:: - - f(dirname, fnames, included_suffixes) - - dirname : str - The name of a directory - fnames : list - The files in that directory - included_suffixes : list - The file suffixes that should be included in the output (passing None - meansto include all suffixes in the output in the built-in formatters) - recursive : boolean - Whether to recurse into subdirectories. Default is True. - - The function should return a list of lines that will be printed in the - notebook (if passing notebook_display_formatter) or the terminal (if - passing terminal_display_formatter). This function is iterated over for - each directory in self.path. Default formatters are in place, can be - passed here to support alternative formatting. - - """ - if isfile(path): - raise ValueError("Cannot display a file using FileLinks. " - "Use FileLink to display '%s'." % path) - self.included_suffixes = included_suffixes - # remove trailing slashes for more consistent output formatting - path = path.rstrip('/') - - self.path = path - self.url_prefix = url_prefix - self.result_html_prefix = result_html_prefix - self.result_html_suffix = result_html_suffix - - self.notebook_display_formatter = \ - notebook_display_formatter or self._get_notebook_display_formatter() - self.terminal_display_formatter = \ - terminal_display_formatter or self._get_terminal_display_formatter() - - self.recursive = recursive - - def _get_display_formatter( - self, dirname_output_format, fname_output_format, fp_format, fp_cleaner=None - ): - """generate built-in formatter function - - this is used to define both the notebook and terminal built-in - formatters as they only differ by some wrapper text for each entry - - dirname_output_format: string to use for formatting directory - names, dirname will be substituted for a single "%s" which - must appear in this string - fname_output_format: string to use for formatting file names, - if a single "%s" appears in the string, fname will be substituted - if two "%s" appear in the string, the path to fname will be - substituted for the first and fname will be substituted for the - second - fp_format: string to use for formatting filepaths, must contain - exactly two "%s" and the dirname will be substituted for the first - and fname will be substituted for the second - """ - def f(dirname, fnames, included_suffixes=None): - result = [] - # begin by figuring out which filenames, if any, - # are going to be displayed - display_fnames = [] - for fname in fnames: - if (isfile(join(dirname,fname)) and - (included_suffixes is None or - splitext(fname)[1] in included_suffixes)): - display_fnames.append(fname) - - if len(display_fnames) == 0: - # if there are no filenames to display, don't print anything - # (not even the directory name) - pass - else: - # otherwise print the formatted directory name followed by - # the formatted filenames - dirname_output_line = dirname_output_format % dirname - result.append(dirname_output_line) - for fname in display_fnames: - fp = fp_format % (dirname,fname) - if fp_cleaner is not None: - fp = fp_cleaner(fp) - try: - # output can include both a filepath and a filename... - fname_output_line = fname_output_format % (fp, fname) - except TypeError: - # ... or just a single filepath - fname_output_line = fname_output_format % fname - result.append(fname_output_line) - return result - return f - - def _get_notebook_display_formatter(self, - spacer=" "): - """ generate function to use for notebook formatting - """ - dirname_output_format = \ - self.result_html_prefix + "%s/" + self.result_html_suffix - fname_output_format = \ - self.result_html_prefix + spacer + self.html_link_str + self.result_html_suffix - fp_format = self.url_prefix + '%s/%s' - if sep == "\\": - # Working on a platform where the path separator is "\", so - # must convert these to "/" for generating a URI - def fp_cleaner(fp): - # Replace all occurrences of backslash ("\") with a forward - # slash ("/") - this is necessary on windows when a path is - # provided as input, but we must link to a URI - return fp.replace('\\','/') - else: - fp_cleaner = None - - return self._get_display_formatter(dirname_output_format, - fname_output_format, - fp_format, - fp_cleaner) - - def _get_terminal_display_formatter(self, - spacer=" "): - """ generate function to use for terminal formatting - """ - dirname_output_format = "%s/" - fname_output_format = spacer + "%s" - fp_format = '%s/%s' - - return self._get_display_formatter(dirname_output_format, - fname_output_format, - fp_format) - - def _format_path(self): - result_lines = [] - if self.recursive: - walked_dir = list(walk(self.path)) - else: - walked_dir = [next(walk(self.path))] - walked_dir.sort() - for dirname, subdirs, fnames in walked_dir: - result_lines += self.notebook_display_formatter(dirname, fnames, self.included_suffixes) - return '\n'.join(result_lines) - - def __repr__(self): - """return newline-separated absolute paths - """ - result_lines = [] - if self.recursive: - walked_dir = list(walk(self.path)) - else: - walked_dir = [next(walk(self.path))] - walked_dir.sort() - for dirname, subdirs, fnames in walked_dir: - result_lines += self.terminal_display_formatter(dirname, fnames, self.included_suffixes) - return '\n'.join(result_lines) - - -class Code(TextDisplayObject): - """Display syntax-highlighted source code. - - This uses Pygments to highlight the code for HTML and Latex output. - - Parameters - ---------- - data : str - The code as a string - url : str - A URL to fetch the code from - filename : str - A local filename to load the code from - language : str - The short name of a Pygments lexer to use for highlighting. - If not specified, it will guess the lexer based on the filename - or the code. Available lexers: http://pygments.org/docs/lexers/ - """ - def __init__(self, data=None, url=None, filename=None, language=None): - self.language = language - super().__init__(data=data, url=url, filename=filename) - - def _get_lexer(self): - if self.language: - from pygments.lexers import get_lexer_by_name - return get_lexer_by_name(self.language) - elif self.filename: - from pygments.lexers import get_lexer_for_filename - return get_lexer_for_filename(self.filename) - else: - from pygments.lexers import guess_lexer - return guess_lexer(self.data) - - def __repr__(self): - return self.data - - def _repr_html_(self): - from pygments import highlight - from pygments.formatters import HtmlFormatter - fmt = HtmlFormatter() - style = '<style>{}</style>'.format(fmt.get_style_defs('.output_html')) - return style + highlight(self.data, self._get_lexer(), fmt) - - def _repr_latex_(self): - from pygments import highlight - from pygments.formatters import LatexFormatter - return highlight(self.data, self._get_lexer(), LatexFormatter()) diff --git a/contrib/python/ipython/py3/IPython/lib/editorhooks.py b/contrib/python/ipython/py3/IPython/lib/editorhooks.py deleted file mode 100644 index d8bd6ac81b..0000000000 --- a/contrib/python/ipython/py3/IPython/lib/editorhooks.py +++ /dev/null @@ -1,127 +0,0 @@ -""" 'editor' hooks for common editors that work well with ipython - -They should honor the line number argument, at least. - -Contributions are *very* welcome. -""" - -import os -import shlex -import subprocess -import sys - -from IPython import get_ipython -from IPython.core.error import TryNext -from IPython.utils import py3compat - - -def install_editor(template, wait=False): - """Installs the editor that is called by IPython for the %edit magic. - - This overrides the default editor, which is generally set by your EDITOR - environment variable or is notepad (windows) or vi (linux). By supplying a - template string `run_template`, you can control how the editor is invoked - by IPython -- (e.g. the format in which it accepts command line options) - - Parameters - ---------- - template : basestring - run_template acts as a template for how your editor is invoked by - the shell. It should contain '{filename}', which will be replaced on - invocation with the file name, and '{line}', $line by line number - (or 0) to invoke the file with. - wait : bool - If `wait` is true, wait until the user presses enter before returning, - to facilitate non-blocking editors that exit immediately after - the call. - """ - - # not all editors support $line, so we'll leave out this check - # for substitution in ['$file', '$line']: - # if not substitution in run_template: - # raise ValueError(('run_template should contain %s' - # ' for string substitution. You supplied "%s"' % (substitution, - # run_template))) - - def call_editor(self, filename, line=0): - if line is None: - line = 0 - cmd = template.format(filename=shlex.quote(filename), line=line) - print(">", cmd) - # shlex.quote doesn't work right on Windows, but it does after splitting - if sys.platform.startswith('win'): - cmd = shlex.split(cmd) - proc = subprocess.Popen(cmd, shell=True) - if proc.wait() != 0: - raise TryNext() - if wait: - py3compat.input("Press Enter when done editing:") - - get_ipython().set_hook('editor', call_editor) - get_ipython().editor = template - - -# in these, exe is always the path/name of the executable. Useful -# if you don't have the editor directory in your path -def komodo(exe=u'komodo'): - """ Activestate Komodo [Edit] """ - install_editor(exe + u' -l {line} {filename}', wait=True) - - -def scite(exe=u"scite"): - """ SciTE or Sc1 """ - install_editor(exe + u' {filename} -goto:{line}') - - -def notepadplusplus(exe=u'notepad++'): - """ Notepad++ http://notepad-plus.sourceforge.net """ - install_editor(exe + u' -n{line} {filename}') - - -def jed(exe=u'jed'): - """ JED, the lightweight emacsish editor """ - install_editor(exe + u' +{line} {filename}') - - -def idle(exe=u'idle'): - """ Idle, the editor bundled with python - - Parameters - ---------- - exe : str, None - If none, should be pretty smart about finding the executable. - """ - if exe is None: - import idlelib - p = os.path.dirname(idlelib.__filename__) - # i'm not sure if this actually works. Is this idle.py script - # guaranteed to be executable? - exe = os.path.join(p, 'idle.py') - install_editor(exe + u' {filename}') - - -def mate(exe=u'mate'): - """ TextMate, the missing editor""" - # wait=True is not required since we're using the -w flag to mate - install_editor(exe + u' -w -l {line} {filename}') - - -# ########################################## -# these are untested, report any problems -# ########################################## - - -def emacs(exe=u'emacs'): - install_editor(exe + u' +{line} {filename}') - - -def gnuclient(exe=u'gnuclient'): - install_editor(exe + u' -nw +{line} {filename}') - - -def crimson_editor(exe=u'cedt.exe'): - install_editor(exe + u' /L:{line} {filename}') - - -def kate(exe=u'kate'): - install_editor(exe + u' -u -l {line} {filename}') diff --git a/contrib/python/ipython/py3/IPython/lib/guisupport.py b/contrib/python/ipython/py3/IPython/lib/guisupport.py deleted file mode 100644 index cfd325e9da..0000000000 --- a/contrib/python/ipython/py3/IPython/lib/guisupport.py +++ /dev/null @@ -1,155 +0,0 @@ -# coding: utf-8 -""" -Support for creating GUI apps and starting event loops. - -IPython's GUI integration allows interactive plotting and GUI usage in IPython -session. IPython has two different types of GUI integration: - -1. The terminal based IPython supports GUI event loops through Python's - PyOS_InputHook. PyOS_InputHook is a hook that Python calls periodically - whenever raw_input is waiting for a user to type code. We implement GUI - support in the terminal by setting PyOS_InputHook to a function that - iterates the event loop for a short while. It is important to note that - in this situation, the real GUI event loop is NOT run in the normal - manner, so you can't use the normal means to detect that it is running. -2. In the two process IPython kernel/frontend, the GUI event loop is run in - the kernel. In this case, the event loop is run in the normal manner by - calling the function or method of the GUI toolkit that starts the event - loop. - -In addition to starting the GUI event loops in one of these two ways, IPython -will *always* create an appropriate GUI application object when GUi -integration is enabled. - -If you want your GUI apps to run in IPython you need to do two things: - -1. Test to see if there is already an existing main application object. If - there is, you should use it. If there is not an existing application object - you should create one. -2. Test to see if the GUI event loop is running. If it is, you should not - start it. If the event loop is not running you may start it. - -This module contains functions for each toolkit that perform these things -in a consistent manner. Because of how PyOS_InputHook runs the event loop -you cannot detect if the event loop is running using the traditional calls -(such as ``wx.GetApp.IsMainLoopRunning()`` in wxPython). If PyOS_InputHook is -set These methods will return a false negative. That is, they will say the -event loop is not running, when is actually is. To work around this limitation -we proposed the following informal protocol: - -* Whenever someone starts the event loop, they *must* set the ``_in_event_loop`` - attribute of the main application object to ``True``. This should be done - regardless of how the event loop is actually run. -* Whenever someone stops the event loop, they *must* set the ``_in_event_loop`` - attribute of the main application object to ``False``. -* If you want to see if the event loop is running, you *must* use ``hasattr`` - to see if ``_in_event_loop`` attribute has been set. If it is set, you - *must* use its value. If it has not been set, you can query the toolkit - in the normal manner. -* If you want GUI support and no one else has created an application or - started the event loop you *must* do this. We don't want projects to - attempt to defer these things to someone else if they themselves need it. - -The functions below implement this logic for each GUI toolkit. If you need -to create custom application subclasses, you will likely have to modify this -code for your own purposes. This code can be copied into your own project -so you don't have to depend on IPython. - -""" - -# Copyright (c) IPython Development Team. -# Distributed under the terms of the Modified BSD License. - -from IPython.core.getipython import get_ipython - -#----------------------------------------------------------------------------- -# wx -#----------------------------------------------------------------------------- - -def get_app_wx(*args, **kwargs): - """Create a new wx app or return an exiting one.""" - import wx - app = wx.GetApp() - if app is None: - if 'redirect' not in kwargs: - kwargs['redirect'] = False - app = wx.PySimpleApp(*args, **kwargs) - return app - -def is_event_loop_running_wx(app=None): - """Is the wx event loop running.""" - # New way: check attribute on shell instance - ip = get_ipython() - if ip is not None: - if ip.active_eventloop and ip.active_eventloop == 'wx': - return True - # Fall through to checking the application, because Wx has a native way - # to check if the event loop is running, unlike Qt. - - # Old way: check Wx application - if app is None: - app = get_app_wx() - if hasattr(app, '_in_event_loop'): - return app._in_event_loop - else: - return app.IsMainLoopRunning() - -def start_event_loop_wx(app=None): - """Start the wx event loop in a consistent manner.""" - if app is None: - app = get_app_wx() - if not is_event_loop_running_wx(app): - app._in_event_loop = True - app.MainLoop() - app._in_event_loop = False - else: - app._in_event_loop = True - -#----------------------------------------------------------------------------- -# qt4 -#----------------------------------------------------------------------------- - -def get_app_qt4(*args, **kwargs): - """Create a new qt4 app or return an existing one.""" - from IPython.external.qt_for_kernel import QtGui - app = QtGui.QApplication.instance() - if app is None: - if not args: - args = ([''],) - app = QtGui.QApplication(*args, **kwargs) - return app - -def is_event_loop_running_qt4(app=None): - """Is the qt4 event loop running.""" - # New way: check attribute on shell instance - ip = get_ipython() - if ip is not None: - return ip.active_eventloop and ip.active_eventloop.startswith('qt') - - # Old way: check attribute on QApplication singleton - if app is None: - app = get_app_qt4(['']) - if hasattr(app, '_in_event_loop'): - return app._in_event_loop - else: - # Does qt4 provide a other way to detect this? - return False - -def start_event_loop_qt4(app=None): - """Start the qt4 event loop in a consistent manner.""" - if app is None: - app = get_app_qt4(['']) - if not is_event_loop_running_qt4(app): - app._in_event_loop = True - app.exec_() - app._in_event_loop = False - else: - app._in_event_loop = True - -#----------------------------------------------------------------------------- -# Tk -#----------------------------------------------------------------------------- - -#----------------------------------------------------------------------------- -# gtk -#----------------------------------------------------------------------------- diff --git a/contrib/python/ipython/py3/IPython/lib/latextools.py b/contrib/python/ipython/py3/IPython/lib/latextools.py deleted file mode 100644 index 27aeef5b0e..0000000000 --- a/contrib/python/ipython/py3/IPython/lib/latextools.py +++ /dev/null @@ -1,246 +0,0 @@ -# -*- coding: utf-8 -*- -"""Tools for handling LaTeX.""" - -# Copyright (c) IPython Development Team. -# Distributed under the terms of the Modified BSD License. - -from io import BytesIO, open -import os -import tempfile -import shutil -import subprocess -from base64 import encodebytes -import textwrap - -from pathlib import Path, PurePath - -from IPython.utils.process import find_cmd, FindCmdError -from traitlets.config import get_config -from traitlets.config.configurable import SingletonConfigurable -from traitlets import List, Bool, Unicode -from IPython.utils.py3compat import cast_unicode - - -class LaTeXTool(SingletonConfigurable): - """An object to store configuration of the LaTeX tool.""" - def _config_default(self): - return get_config() - - backends = List( - Unicode(), ["matplotlib", "dvipng"], - help="Preferred backend to draw LaTeX math equations. " - "Backends in the list are checked one by one and the first " - "usable one is used. Note that `matplotlib` backend " - "is usable only for inline style equations. To draw " - "display style equations, `dvipng` backend must be specified. ", - # It is a List instead of Enum, to make configuration more - # flexible. For example, to use matplotlib mainly but dvipng - # 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) - - use_breqn = Bool( - True, - help="Use breqn.sty to automatically break long equations. " - "This configuration takes effect only for dvipng backend.", - ).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) - - preamble = Unicode( - help="Additional preamble to use when generating LaTeX source " - "for dvipng backend.", - ).tag(config=True) - - -def latex_to_png(s, encode=False, backend=None, wrap=False, color='Black', - scale=1.0): - """Render a LaTeX string to PNG. - - Parameters - ---------- - s : str - The raw string containing valid inline LaTeX. - encode : bool, optional - Should the PNG data base64 encoded to make it JSON'able. - backend : {matplotlib, dvipng} - Backend for producing PNG data. - wrap : bool - If true, Automatically wrap `s` as a LaTeX equation. - color : string - Foreground color name among dvipsnames, e.g. 'Maroon' or on hex RGB - format, e.g. '#AA20FA'. - scale : float - Scale factor for the resulting PNG. - None is returned when the backend cannot be used. - - """ - s = cast_unicode(s) - allowed_backends = LaTeXTool.instance().backends - if backend is None: - backend = allowed_backends[0] - if backend not in allowed_backends: - return None - if backend == 'matplotlib': - f = latex_to_png_mpl - elif backend == 'dvipng': - f = latex_to_png_dvipng - if color.startswith('#'): - # Convert hex RGB color to LaTeX RGB color. - if len(color) == 7: - try: - color = "RGB {}".format(" ".join([str(int(x, 16)) for x in - textwrap.wrap(color[1:], 2)])) - except ValueError as e: - raise ValueError('Invalid color specification {}.'.format(color)) from e - else: - raise ValueError('Invalid color specification {}.'.format(color)) - else: - raise ValueError('No such backend {0}'.format(backend)) - bin_data = f(s, wrap, color, scale) - if encode and bin_data: - bin_data = encodebytes(bin_data) - return bin_data - - -def latex_to_png_mpl(s, wrap, color='Black', scale=1.0): - try: - from matplotlib import figure, font_manager, mathtext - from matplotlib.backends import backend_agg - 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: - prop = font_manager.FontProperties(size=12) - dpi = 120 * scale - buffer = BytesIO() - - # Adapted from mathtext.math_to_image - parser = mathtext.MathTextParser("path") - width, height, depth, _, _ = parser.parse(s, dpi=72, prop=prop) - fig = figure.Figure(figsize=(width / 72, height / 72)) - fig.text(0, depth / height, s, fontproperties=prop, color=color) - backend_agg.FigureCanvasAgg(fig) - fig.savefig(buffer, dpi=dpi, format="png", transparent=True) - return buffer.getvalue() - except (ValueError, RuntimeError, ParseFatalException): - return None - - -def latex_to_png_dvipng(s, wrap, color='Black', scale=1.0): - try: - find_cmd('latex') - find_cmd('dvipng') - except FindCmdError: - return None - try: - workdir = Path(tempfile.mkdtemp()) - tmpfile = workdir.joinpath("tmp.tex") - dvifile = workdir.joinpath("tmp.dvi") - outfile = workdir.joinpath("tmp.png") - - with tmpfile.open("w", encoding="utf8") as f: - f.writelines(genelatex(s, wrap)) - - with open(os.devnull, 'wb') as devnull: - subprocess.check_call( - ["latex", "-halt-on-error", "-interaction", "batchmode", tmpfile], - cwd=workdir, stdout=devnull, stderr=devnull) - - resolution = round(150*scale) - subprocess.check_call( - [ - "dvipng", - "-T", - "tight", - "-D", - str(resolution), - "-z", - "9", - "-bg", - "Transparent", - "-o", - outfile, - dvifile, - "-fg", - color, - ], - cwd=workdir, - stdout=devnull, - stderr=devnull, - ) - - with outfile.open("rb") as f: - return f.read() - except subprocess.CalledProcessError: - return None - finally: - shutil.rmtree(workdir) - - -def kpsewhich(filename): - """Invoke kpsewhich command with an argument `filename`.""" - try: - find_cmd("kpsewhich") - proc = subprocess.Popen( - ["kpsewhich", filename], - stdout=subprocess.PIPE, stderr=subprocess.PIPE) - (stdout, stderr) = proc.communicate() - return stdout.strip().decode('utf8', 'replace') - except FindCmdError: - pass - - -def genelatex(body, wrap): - """Generate LaTeX document for dvipng backend.""" - lt = LaTeXTool.instance() - breqn = wrap and lt.use_breqn and kpsewhich("breqn.sty") - yield r'\documentclass{article}' - packages = lt.packages - if breqn: - packages = packages + ['breqn'] - for pack in packages: - yield r'\usepackage{{{0}}}'.format(pack) - yield r'\pagestyle{empty}' - if lt.preamble: - yield lt.preamble - yield r'\begin{document}' - if breqn: - yield r'\begin{dmath*}' - yield body - yield r'\end{dmath*}' - elif wrap: - yield u'$${0}$$'.format(body) - else: - yield body - yield u'\\end{document}' - - -_data_uri_template_png = u"""<img src="data:image/png;base64,%s" alt=%s />""" - -def latex_to_html(s, alt='image'): - """Render LaTeX to HTML with embedded PNG data using data URIs. - - Parameters - ---------- - s : str - The raw string containing valid inline LateX. - alt : str - The alt text to use for the HTML. - """ - base64_data = latex_to_png(s, encode=True).decode('ascii') - if base64_data: - return _data_uri_template_png % (base64_data, alt) - - diff --git a/contrib/python/ipython/py3/IPython/lib/lexers.py b/contrib/python/ipython/py3/IPython/lib/lexers.py deleted file mode 100644 index 0c9b6e1bc7..0000000000 --- a/contrib/python/ipython/py3/IPython/lib/lexers.py +++ /dev/null @@ -1,526 +0,0 @@ -# -*- coding: utf-8 -*- -""" -Defines a variety of Pygments lexers for highlighting IPython code. - -This includes: - - IPythonLexer, IPython3Lexer - Lexers for pure IPython (python + magic/shell commands) - - IPythonPartialTracebackLexer, IPythonTracebackLexer - Supports 2.x and 3.x via keyword `python3`. The partial traceback - lexer reads everything but the Python code appearing in a traceback. - The full lexer combines the partial lexer with an IPython lexer. - - IPythonConsoleLexer - A lexer for IPython console sessions, with support for tracebacks. - - IPyLexer - A friendly lexer which examines the first line of text and from it, - decides whether to use an IPython lexer or an IPython console lexer. - This is probably the only lexer that needs to be explicitly added - to Pygments. - -""" -#----------------------------------------------------------------------------- -# Copyright (c) 2013, the IPython Development Team. -# -# Distributed under the terms of the Modified BSD License. -# -# The full license is in the file COPYING.txt, distributed with this software. -#----------------------------------------------------------------------------- - -# Standard library -import re - -# Third party -from pygments.lexers import ( - BashLexer, HtmlLexer, JavascriptLexer, RubyLexer, PerlLexer, PythonLexer, - Python3Lexer, TexLexer) -from pygments.lexer import ( - Lexer, DelegatingLexer, RegexLexer, do_insertions, bygroups, using, -) -from pygments.token import ( - Generic, Keyword, Literal, Name, Operator, Other, Text, Error, -) -from pygments.util import get_bool_opt - -# Local - -line_re = re.compile('.*?\n') - -__all__ = ['build_ipy_lexer', 'IPython3Lexer', 'IPythonLexer', - 'IPythonPartialTracebackLexer', 'IPythonTracebackLexer', - 'IPythonConsoleLexer', 'IPyLexer'] - - -def build_ipy_lexer(python3): - """Builds IPython lexers depending on the value of `python3`. - - The lexer inherits from an appropriate Python lexer and then adds - information about IPython specific keywords (i.e. magic commands, - shell commands, etc.) - - Parameters - ---------- - python3 : bool - If `True`, then build an IPython lexer from a Python 3 lexer. - - """ - # It would be nice to have a single IPython lexer class which takes - # a boolean `python3`. But since there are two Python lexer classes, - # we will also have two IPython lexer classes. - if python3: - PyLexer = Python3Lexer - name = 'IPython3' - aliases = ['ipython3'] - doc = """IPython3 Lexer""" - else: - PyLexer = PythonLexer - name = 'IPython' - aliases = ['ipython2', 'ipython'] - doc = """IPython Lexer""" - - ipython_tokens = [ - (r'(?s)(\s*)(%%capture)([^\n]*\n)(.*)', bygroups(Text, Operator, Text, using(PyLexer))), - (r'(?s)(\s*)(%%debug)([^\n]*\n)(.*)', bygroups(Text, Operator, Text, using(PyLexer))), - (r'(?is)(\s*)(%%html)([^\n]*\n)(.*)', bygroups(Text, Operator, Text, using(HtmlLexer))), - (r'(?s)(\s*)(%%javascript)([^\n]*\n)(.*)', bygroups(Text, Operator, Text, using(JavascriptLexer))), - (r'(?s)(\s*)(%%js)([^\n]*\n)(.*)', bygroups(Text, Operator, Text, using(JavascriptLexer))), - (r'(?s)(\s*)(%%latex)([^\n]*\n)(.*)', bygroups(Text, Operator, Text, using(TexLexer))), - (r'(?s)(\s*)(%%perl)([^\n]*\n)(.*)', bygroups(Text, Operator, Text, using(PerlLexer))), - (r'(?s)(\s*)(%%prun)([^\n]*\n)(.*)', bygroups(Text, Operator, Text, using(PyLexer))), - (r'(?s)(\s*)(%%pypy)([^\n]*\n)(.*)', bygroups(Text, Operator, Text, using(PyLexer))), - (r'(?s)(\s*)(%%python)([^\n]*\n)(.*)', bygroups(Text, Operator, Text, using(PyLexer))), - (r'(?s)(\s*)(%%python2)([^\n]*\n)(.*)', bygroups(Text, Operator, Text, using(PythonLexer))), - (r'(?s)(\s*)(%%python3)([^\n]*\n)(.*)', bygroups(Text, Operator, Text, using(Python3Lexer))), - (r'(?s)(\s*)(%%ruby)([^\n]*\n)(.*)', bygroups(Text, Operator, Text, using(RubyLexer))), - (r'(?s)(\s*)(%%time)([^\n]*\n)(.*)', bygroups(Text, Operator, Text, using(PyLexer))), - (r'(?s)(\s*)(%%timeit)([^\n]*\n)(.*)', bygroups(Text, Operator, Text, using(PyLexer))), - (r'(?s)(\s*)(%%writefile)([^\n]*\n)(.*)', bygroups(Text, Operator, Text, using(PyLexer))), - (r'(?s)(\s*)(%%file)([^\n]*\n)(.*)', bygroups(Text, Operator, Text, using(PyLexer))), - (r"(?s)(\s*)(%%)(\w+)(.*)", bygroups(Text, Operator, Keyword, Text)), - (r'(?s)(^\s*)(%%!)([^\n]*\n)(.*)', bygroups(Text, Operator, Text, using(BashLexer))), - (r"(%%?)(\w+)(\?\??)$", bygroups(Operator, Keyword, Operator)), - (r"\b(\?\??)(\s*)$", bygroups(Operator, Text)), - (r'(%)(sx|sc|system)(.*)(\n)', bygroups(Operator, Keyword, - using(BashLexer), Text)), - (r'(%)(\w+)(.*\n)', bygroups(Operator, Keyword, Text)), - (r'^(!!)(.+)(\n)', bygroups(Operator, using(BashLexer), Text)), - (r'(!)(?!=)(.+)(\n)', bygroups(Operator, using(BashLexer), Text)), - (r'^(\s*)(\?\??)(\s*%{0,2}[\w\.\*]*)', bygroups(Text, Operator, Text)), - (r'(\s*%{0,2}[\w\.\*]*)(\?\??)(\s*)$', bygroups(Text, Operator, Text)), - ] - - tokens = PyLexer.tokens.copy() - tokens['root'] = ipython_tokens + tokens['root'] - - attrs = {'name': name, 'aliases': aliases, 'filenames': [], - '__doc__': doc, 'tokens': tokens} - - return type(name, (PyLexer,), attrs) - - -IPython3Lexer = build_ipy_lexer(python3=True) -IPythonLexer = build_ipy_lexer(python3=False) - - -class IPythonPartialTracebackLexer(RegexLexer): - """ - Partial lexer for IPython tracebacks. - - Handles all the non-python output. - - """ - name = 'IPython Partial Traceback' - - tokens = { - 'root': [ - # Tracebacks for syntax errors have a different style. - # For both types of tracebacks, we mark the first line with - # Generic.Traceback. For syntax errors, we mark the filename - # as we mark the filenames for non-syntax tracebacks. - # - # These two regexps define how IPythonConsoleLexer finds a - # traceback. - # - ## Non-syntax traceback - (r'^(\^C)?(-+\n)', bygroups(Error, Generic.Traceback)), - ## Syntax traceback - (r'^( File)(.*)(, line )(\d+\n)', - bygroups(Generic.Traceback, Name.Namespace, - Generic.Traceback, Literal.Number.Integer)), - - # (Exception Identifier)(Whitespace)(Traceback Message) - (r'(?u)(^[^\d\W]\w*)(\s*)(Traceback.*?\n)', - bygroups(Name.Exception, Generic.Whitespace, Text)), - # (Module/Filename)(Text)(Callee)(Function Signature) - # Better options for callee and function signature? - (r'(.*)( in )(.*)(\(.*\)\n)', - bygroups(Name.Namespace, Text, Name.Entity, Name.Tag)), - # Regular line: (Whitespace)(Line Number)(Python Code) - (r'(\s*?)(\d+)(.*?\n)', - bygroups(Generic.Whitespace, Literal.Number.Integer, Other)), - # Emphasized line: (Arrow)(Line Number)(Python Code) - # Using Exception token so arrow color matches the Exception. - (r'(-*>?\s?)(\d+)(.*?\n)', - bygroups(Name.Exception, Literal.Number.Integer, Other)), - # (Exception Identifier)(Message) - (r'(?u)(^[^\d\W]\w*)(:.*?\n)', - bygroups(Name.Exception, Text)), - # Tag everything else as Other, will be handled later. - (r'.*\n', Other), - ], - } - - -class IPythonTracebackLexer(DelegatingLexer): - """ - IPython traceback lexer. - - For doctests, the tracebacks can be snipped as much as desired with the - exception to the lines that designate a traceback. For non-syntax error - tracebacks, this is the line of hyphens. For syntax error tracebacks, - this is the line which lists the File and line number. - - """ - # The lexer inherits from DelegatingLexer. The "root" lexer is an - # appropriate IPython lexer, which depends on the value of the boolean - # `python3`. First, we parse with the partial IPython traceback lexer. - # Then, any code marked with the "Other" token is delegated to the root - # lexer. - # - name = 'IPython Traceback' - aliases = ['ipythontb'] - - def __init__(self, **options): - self.python3 = get_bool_opt(options, 'python3', False) - if self.python3: - self.aliases = ['ipython3tb'] - else: - self.aliases = ['ipython2tb', 'ipythontb'] - - if self.python3: - IPyLexer = IPython3Lexer - else: - IPyLexer = IPythonLexer - - DelegatingLexer.__init__(self, IPyLexer, - IPythonPartialTracebackLexer, **options) - -class IPythonConsoleLexer(Lexer): - """ - An IPython console lexer for IPython code-blocks and doctests, such as: - - .. code-block:: rst - - .. code-block:: ipythonconsole - - In [1]: a = 'foo' - - In [2]: a - Out[2]: 'foo' - - In [3]: print(a) - foo - - - Support is also provided for IPython exceptions: - - .. code-block:: rst - - .. code-block:: ipythonconsole - - In [1]: raise Exception - Traceback (most recent call last): - ... - Exception - - """ - name = 'IPython console session' - aliases = ['ipythonconsole'] - mimetypes = ['text/x-ipython-console'] - - # 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 - # - in1_regex = r'In \[[0-9]+\]: ' - in2_regex = r' \.\.+\.: ' - out_regex = r'Out\[[0-9]+\]: ' - - #: The regex to determine when a traceback starts. - ipytb_start = re.compile(r'^(\^C)?(-+\n)|^( File)(.*)(, line )(\d+\n)') - - def __init__(self, **options): - """Initialize the IPython console lexer. - - Parameters - ---------- - python3 : bool - If `True`, then the console inputs are parsed using a Python 3 - lexer. Otherwise, they are parsed using a Python 2 lexer. - in1_regex : RegexObject - The compiled regular expression used to detect the start - of inputs. Although the IPython configuration setting may have a - trailing whitespace, do not include it in the regex. If `None`, - then the default input prompt is assumed. - in2_regex : RegexObject - The compiled regular expression used to detect the continuation - of inputs. Although the IPython configuration setting may have a - trailing whitespace, do not include it in the regex. If `None`, - then the default input prompt is assumed. - out_regex : RegexObject - The compiled regular expression used to detect outputs. If `None`, - then the default output prompt is assumed. - - """ - self.python3 = get_bool_opt(options, 'python3', False) - if self.python3: - self.aliases = ['ipython3console'] - else: - self.aliases = ['ipython2console', 'ipythonconsole'] - - in1_regex = options.get('in1_regex', self.in1_regex) - in2_regex = options.get('in2_regex', self.in2_regex) - out_regex = options.get('out_regex', self.out_regex) - - # So that we can work with input and output prompts which have been - # rstrip'd (possibly by editors) we also need rstrip'd variants. If - # we do not do this, then such prompts will be tagged as 'output'. - # The reason can't just use the rstrip'd variants instead is because - # we want any whitespace associated with the prompt to be inserted - # with the token. This allows formatted code to be modified so as hide - # the appearance of prompts, with the whitespace included. One example - # use of this is in copybutton.js from the standard lib Python docs. - in1_regex_rstrip = in1_regex.rstrip() + '\n' - in2_regex_rstrip = in2_regex.rstrip() + '\n' - out_regex_rstrip = out_regex.rstrip() + '\n' - - # Compile and save them all. - attrs = ['in1_regex', 'in2_regex', 'out_regex', - 'in1_regex_rstrip', 'in2_regex_rstrip', 'out_regex_rstrip'] - for attr in attrs: - self.__setattr__(attr, re.compile(locals()[attr])) - - Lexer.__init__(self, **options) - - if self.python3: - pylexer = IPython3Lexer - tblexer = IPythonTracebackLexer - else: - pylexer = IPythonLexer - tblexer = IPythonTracebackLexer - - self.pylexer = pylexer(**options) - self.tblexer = tblexer(**options) - - self.reset() - - def reset(self): - self.mode = 'output' - self.index = 0 - self.buffer = u'' - self.insertions = [] - - def buffered_tokens(self): - """ - Generator of unprocessed tokens after doing insertions and before - changing to a new state. - - """ - if self.mode == 'output': - tokens = [(0, Generic.Output, self.buffer)] - elif self.mode == 'input': - tokens = self.pylexer.get_tokens_unprocessed(self.buffer) - else: # traceback - tokens = self.tblexer.get_tokens_unprocessed(self.buffer) - - for i, t, v in do_insertions(self.insertions, tokens): - # All token indexes are relative to the buffer. - yield self.index + i, t, v - - # Clear it all - self.index += len(self.buffer) - self.buffer = u'' - self.insertions = [] - - def get_mci(self, line): - """ - Parses the line and returns a 3-tuple: (mode, code, insertion). - - `mode` is the next mode (or state) of the lexer, and is always equal - to 'input', 'output', or 'tb'. - - `code` is a portion of the line that should be added to the buffer - corresponding to the next mode and eventually lexed by another lexer. - For example, `code` could be Python code if `mode` were 'input'. - - `insertion` is a 3-tuple (index, token, text) representing an - unprocessed "token" that will be inserted into the stream of tokens - that are created from the buffer once we change modes. This is usually - the input or output prompt. - - In general, the next mode depends on current mode and on the contents - of `line`. - - """ - # To reduce the number of regex match checks, we have multiple - # 'if' blocks instead of 'if-elif' blocks. - - # Check for possible end of input - in2_match = self.in2_regex.match(line) - in2_match_rstrip = self.in2_regex_rstrip.match(line) - if (in2_match and in2_match.group().rstrip() == line.rstrip()) or \ - in2_match_rstrip: - end_input = True - else: - end_input = False - if end_input and self.mode != 'tb': - # Only look for an end of input when not in tb mode. - # An ellipsis could appear within the traceback. - mode = 'output' - code = u'' - insertion = (0, Generic.Prompt, line) - return mode, code, insertion - - # Check for output prompt - out_match = self.out_regex.match(line) - out_match_rstrip = self.out_regex_rstrip.match(line) - if out_match or out_match_rstrip: - mode = 'output' - if out_match: - idx = out_match.end() - else: - idx = out_match_rstrip.end() - code = line[idx:] - # Use the 'heading' token for output. We cannot use Generic.Error - # since it would conflict with exceptions. - insertion = (0, Generic.Heading, line[:idx]) - return mode, code, insertion - - - # Check for input or continuation prompt (non stripped version) - in1_match = self.in1_regex.match(line) - if in1_match or (in2_match and self.mode != 'tb'): - # New input or when not in tb, continued input. - # We do not check for continued input when in tb since it is - # allowable to replace a long stack with an ellipsis. - mode = 'input' - if in1_match: - idx = in1_match.end() - else: # in2_match - idx = in2_match.end() - code = line[idx:] - insertion = (0, Generic.Prompt, line[:idx]) - return mode, code, insertion - - # Check for input or continuation prompt (stripped version) - in1_match_rstrip = self.in1_regex_rstrip.match(line) - if in1_match_rstrip or (in2_match_rstrip and self.mode != 'tb'): - # New input or when not in tb, continued input. - # We do not check for continued input when in tb since it is - # allowable to replace a long stack with an ellipsis. - mode = 'input' - if in1_match_rstrip: - idx = in1_match_rstrip.end() - else: # in2_match - idx = in2_match_rstrip.end() - code = line[idx:] - insertion = (0, Generic.Prompt, line[:idx]) - return mode, code, insertion - - # Check for traceback - if self.ipytb_start.match(line): - mode = 'tb' - code = line - insertion = None - return mode, code, insertion - - # All other stuff... - if self.mode in ('input', 'output'): - # We assume all other text is output. Multiline input that - # does not use the continuation marker cannot be detected. - # For example, the 3 in the following is clearly output: - # - # In [1]: print 3 - # 3 - # - # But the following second line is part of the input: - # - # In [2]: while True: - # print True - # - # In both cases, the 2nd line will be 'output'. - # - mode = 'output' - else: - mode = 'tb' - - code = line - insertion = None - - return mode, code, insertion - - def get_tokens_unprocessed(self, text): - self.reset() - for match in line_re.finditer(text): - line = match.group() - mode, code, insertion = self.get_mci(line) - - if mode != self.mode: - # Yield buffered tokens before transitioning to new mode. - for token in self.buffered_tokens(): - yield token - self.mode = mode - - if insertion: - self.insertions.append((len(self.buffer), [insertion])) - self.buffer += code - - for token in self.buffered_tokens(): - yield token - -class IPyLexer(Lexer): - r""" - Primary lexer for all IPython-like code. - - This is a simple helper lexer. If the first line of the text begins with - "In \[[0-9]+\]:", then the entire text is parsed with an IPython console - lexer. If not, then the entire text is parsed with an IPython lexer. - - The goal is to reduce the number of lexers that are registered - with Pygments. - - """ - name = 'IPy session' - aliases = ['ipy'] - - def __init__(self, **options): - self.python3 = get_bool_opt(options, 'python3', False) - if self.python3: - self.aliases = ['ipy3'] - else: - self.aliases = ['ipy2', 'ipy'] - - Lexer.__init__(self, **options) - - self.IPythonLexer = IPythonLexer(**options) - self.IPythonConsoleLexer = IPythonConsoleLexer(**options) - - def get_tokens_unprocessed(self, text): - # Search for the input prompt anywhere...this allows code blocks to - # begin with comments as well. - if re.match(r'.*(In \[[0-9]+\]:)', text.strip(), re.DOTALL): - lex = self.IPythonConsoleLexer - else: - lex = self.IPythonLexer - for token in lex.get_tokens_unprocessed(text): - yield token - diff --git a/contrib/python/ipython/py3/IPython/lib/pretty.py b/contrib/python/ipython/py3/IPython/lib/pretty.py deleted file mode 100644 index 72f143522d..0000000000 --- a/contrib/python/ipython/py3/IPython/lib/pretty.py +++ /dev/null @@ -1,951 +0,0 @@ -# -*- coding: utf-8 -*- -""" -Python advanced pretty printer. This pretty printer is intended to -replace the old `pprint` python module which does not allow developers -to provide their own pretty print callbacks. - -This module is based on ruby's `prettyprint.rb` library by `Tanaka Akira`. - - -Example Usage -------------- - -To directly print the representation of an object use `pprint`:: - - from pretty import pprint - pprint(complex_object) - -To get a string of the output use `pretty`:: - - from pretty import pretty - string = pretty(complex_object) - - -Extending ---------- - -The pretty library allows developers to add pretty printing rules for their -own objects. This process is straightforward. All you have to do is to -add a `_repr_pretty_` method to your object and call the methods on the -pretty printer passed:: - - class MyObject(object): - - def _repr_pretty_(self, p, cycle): - ... - -Here's an example for a class with a simple constructor:: - - class MySimpleObject: - - def __init__(self, a, b, *, c=None): - self.a = a - self.b = b - self.c = c - - def _repr_pretty_(self, p, cycle): - ctor = CallExpression.factory(self.__class__.__name__) - if self.c is None: - p.pretty(ctor(a, b)) - else: - p.pretty(ctor(a, b, c=c)) - -Here is an example implementation of a `_repr_pretty_` method for a list -subclass:: - - class MyList(list): - - def _repr_pretty_(self, p, cycle): - if cycle: - p.text('MyList(...)') - else: - with p.group(8, 'MyList([', '])'): - for idx, item in enumerate(self): - if idx: - p.text(',') - p.breakable() - p.pretty(item) - -The `cycle` parameter is `True` if pretty detected a cycle. You *have* to -react to that or the result is an infinite loop. `p.text()` just adds -non breaking text to the output, `p.breakable()` either adds a whitespace -or breaks here. If you pass it an argument it's used instead of the -default space. `p.pretty` prettyprints another object using the pretty print -method. - -The first parameter to the `group` function specifies the extra indentation -of the next line. In this example the next item will either be on the same -line (if the items are short enough) or aligned with the right edge of the -opening bracket of `MyList`. - -If you just want to indent something you can use the group function -without open / close parameters. You can also use this code:: - - with p.indent(2): - ... - -Inheritance diagram: - -.. inheritance-diagram:: IPython.lib.pretty - :parts: 3 - -:copyright: 2007 by Armin Ronacher. - Portions (c) 2009 by Robert Kern. -:license: BSD License. -""" - -from contextlib import contextmanager -import datetime -import os -import re -import sys -import types -from collections import deque -from inspect import signature -from io import StringIO -from warnings import warn - -from IPython.utils.decorators import undoc -from IPython.utils.py3compat import PYPY - -__all__ = ['pretty', 'pprint', 'PrettyPrinter', 'RepresentationPrinter', - 'for_type', 'for_type_by_name', 'RawText', 'RawStringLiteral', 'CallExpression'] - - -MAX_SEQ_LENGTH = 1000 -_re_pattern_type = type(re.compile('')) - -def _safe_getattr(obj, attr, default=None): - """Safe version of getattr. - - Same as getattr, but will return ``default`` on any Exception, - rather than raising. - """ - try: - return getattr(obj, attr, default) - except Exception: - return default - -@undoc -class CUnicodeIO(StringIO): - def __init__(self, *args, **kwargs): - super().__init__(*args, **kwargs) - warn(("CUnicodeIO is deprecated since IPython 6.0. " - "Please use io.StringIO instead."), - DeprecationWarning, stacklevel=2) - -def _sorted_for_pprint(items): - """ - Sort the given items for pretty printing. Since some predictable - sorting is better than no sorting at all, we sort on the string - representation if normal sorting fails. - """ - items = list(items) - try: - return sorted(items) - except Exception: - try: - return sorted(items, key=str) - except Exception: - return items - -def pretty(obj, verbose=False, max_width=79, newline='\n', max_seq_length=MAX_SEQ_LENGTH): - """ - Pretty print the object's representation. - """ - stream = StringIO() - printer = RepresentationPrinter(stream, verbose, max_width, newline, max_seq_length=max_seq_length) - printer.pretty(obj) - printer.flush() - return stream.getvalue() - - -def pprint(obj, verbose=False, max_width=79, newline='\n', max_seq_length=MAX_SEQ_LENGTH): - """ - Like `pretty` but print to stdout. - """ - printer = RepresentationPrinter(sys.stdout, verbose, max_width, newline, max_seq_length=max_seq_length) - printer.pretty(obj) - printer.flush() - sys.stdout.write(newline) - sys.stdout.flush() - -class _PrettyPrinterBase(object): - - @contextmanager - def indent(self, indent): - """with statement support for indenting/dedenting.""" - self.indentation += indent - try: - yield - finally: - self.indentation -= indent - - @contextmanager - def group(self, indent=0, open='', close=''): - """like begin_group / end_group but for the with statement.""" - self.begin_group(indent, open) - try: - yield - finally: - self.end_group(indent, close) - -class PrettyPrinter(_PrettyPrinterBase): - """ - Baseclass for the `RepresentationPrinter` prettyprinter that is used to - generate pretty reprs of objects. Contrary to the `RepresentationPrinter` - this printer knows nothing about the default pprinters or the `_repr_pretty_` - callback method. - """ - - def __init__(self, output, max_width=79, newline='\n', max_seq_length=MAX_SEQ_LENGTH): - self.output = output - self.max_width = max_width - self.newline = newline - self.max_seq_length = max_seq_length - self.output_width = 0 - self.buffer_width = 0 - self.buffer = deque() - - root_group = Group(0) - self.group_stack = [root_group] - self.group_queue = GroupQueue(root_group) - self.indentation = 0 - - def _break_one_group(self, group): - while group.breakables: - x = self.buffer.popleft() - self.output_width = x.output(self.output, self.output_width) - self.buffer_width -= x.width - while self.buffer and isinstance(self.buffer[0], Text): - x = self.buffer.popleft() - self.output_width = x.output(self.output, self.output_width) - self.buffer_width -= x.width - - def _break_outer_groups(self): - while self.max_width < self.output_width + self.buffer_width: - group = self.group_queue.deq() - if not group: - return - self._break_one_group(group) - - def text(self, obj): - """Add literal text to the output.""" - width = len(obj) - if self.buffer: - text = self.buffer[-1] - if not isinstance(text, Text): - text = Text() - self.buffer.append(text) - text.add(obj, width) - self.buffer_width += width - self._break_outer_groups() - else: - self.output.write(obj) - self.output_width += width - - def breakable(self, sep=' '): - """ - Add a breakable separator to the output. This does not mean that it - will automatically break here. If no breaking on this position takes - place the `sep` is inserted which default to one space. - """ - width = len(sep) - group = self.group_stack[-1] - if group.want_break: - self.flush() - self.output.write(self.newline) - self.output.write(' ' * self.indentation) - self.output_width = self.indentation - self.buffer_width = 0 - else: - self.buffer.append(Breakable(sep, width, self)) - self.buffer_width += width - self._break_outer_groups() - - def break_(self): - """ - Explicitly insert a newline into the output, maintaining correct indentation. - """ - group = self.group_queue.deq() - if group: - self._break_one_group(group) - self.flush() - self.output.write(self.newline) - self.output.write(' ' * self.indentation) - self.output_width = self.indentation - self.buffer_width = 0 - - - def begin_group(self, indent=0, open=''): - """ - Begin a group. - The first parameter specifies the indentation for the next line (usually - the width of the opening text), the second the opening text. All - parameters are optional. - """ - if open: - self.text(open) - group = Group(self.group_stack[-1].depth + 1) - self.group_stack.append(group) - self.group_queue.enq(group) - self.indentation += indent - - def _enumerate(self, seq): - """like enumerate, but with an upper limit on the number of items""" - for idx, x in enumerate(seq): - if self.max_seq_length and idx >= self.max_seq_length: - self.text(',') - self.breakable() - self.text('...') - return - yield idx, x - - def end_group(self, dedent=0, close=''): - """End a group. See `begin_group` for more details.""" - self.indentation -= dedent - group = self.group_stack.pop() - if not group.breakables: - self.group_queue.remove(group) - if close: - self.text(close) - - def flush(self): - """Flush data that is left in the buffer.""" - for data in self.buffer: - self.output_width += data.output(self.output, self.output_width) - self.buffer.clear() - self.buffer_width = 0 - - -def _get_mro(obj_class): - """ Get a reasonable method resolution order of a class and its superclasses - for both old-style and new-style classes. - """ - if not hasattr(obj_class, '__mro__'): - # Old-style class. Mix in object to make a fake new-style class. - try: - obj_class = type(obj_class.__name__, (obj_class, object), {}) - except TypeError: - # Old-style extension type that does not descend from object. - # FIXME: try to construct a more thorough MRO. - mro = [obj_class] - else: - mro = obj_class.__mro__[1:-1] - else: - mro = obj_class.__mro__ - return mro - - -class RepresentationPrinter(PrettyPrinter): - """ - Special pretty printer that has a `pretty` method that calls the pretty - printer for a python object. - - This class stores processing data on `self` so you must *never* use - this class in a threaded environment. Always lock it or reinstanciate - it. - - Instances also have a verbose flag callbacks can access to control their - output. For example the default instance repr prints all attributes and - methods that are not prefixed by an underscore if the printer is in - verbose mode. - """ - - def __init__(self, output, verbose=False, max_width=79, newline='\n', - singleton_pprinters=None, type_pprinters=None, deferred_pprinters=None, - max_seq_length=MAX_SEQ_LENGTH): - - PrettyPrinter.__init__(self, output, max_width, newline, max_seq_length=max_seq_length) - self.verbose = verbose - self.stack = [] - if singleton_pprinters is None: - singleton_pprinters = _singleton_pprinters.copy() - self.singleton_pprinters = singleton_pprinters - if type_pprinters is None: - type_pprinters = _type_pprinters.copy() - self.type_pprinters = type_pprinters - if deferred_pprinters is None: - deferred_pprinters = _deferred_type_pprinters.copy() - self.deferred_pprinters = deferred_pprinters - - def pretty(self, obj): - """Pretty print the given object.""" - obj_id = id(obj) - cycle = obj_id in self.stack - self.stack.append(obj_id) - self.begin_group() - try: - obj_class = _safe_getattr(obj, '__class__', None) or type(obj) - # First try to find registered singleton printers for the type. - try: - printer = self.singleton_pprinters[obj_id] - except (TypeError, KeyError): - pass - else: - return printer(obj, self, cycle) - # Next walk the mro and check for either: - # 1) a registered printer - # 2) a _repr_pretty_ method - for cls in _get_mro(obj_class): - if cls in self.type_pprinters: - # printer registered in self.type_pprinters - return self.type_pprinters[cls](obj, self, cycle) - else: - # deferred printer - printer = self._in_deferred_types(cls) - if printer is not None: - return printer(obj, self, cycle) - else: - # Finally look for special method names. - # Some objects automatically create any requested - # attribute. Try to ignore most of them by checking for - # callability. - if '_repr_pretty_' in cls.__dict__: - meth = cls._repr_pretty_ - if callable(meth): - return meth(obj, self, cycle) - if cls is not object \ - and callable(cls.__dict__.get('__repr__')): - return _repr_pprint(obj, self, cycle) - - return _default_pprint(obj, self, cycle) - finally: - self.end_group() - self.stack.pop() - - def _in_deferred_types(self, cls): - """ - Check if the given class is specified in the deferred type registry. - - Returns the printer from the registry if it exists, and None if the - class is not in the registry. Successful matches will be moved to the - regular type registry for future use. - """ - mod = _safe_getattr(cls, '__module__', None) - name = _safe_getattr(cls, '__name__', None) - key = (mod, name) - printer = None - if key in self.deferred_pprinters: - # Move the printer over to the regular registry. - printer = self.deferred_pprinters.pop(key) - self.type_pprinters[cls] = printer - return printer - - -class Printable(object): - - def output(self, stream, output_width): - return output_width - - -class Text(Printable): - - def __init__(self): - self.objs = [] - self.width = 0 - - def output(self, stream, output_width): - for obj in self.objs: - stream.write(obj) - return output_width + self.width - - def add(self, obj, width): - self.objs.append(obj) - self.width += width - - -class Breakable(Printable): - - def __init__(self, seq, width, pretty): - self.obj = seq - self.width = width - self.pretty = pretty - self.indentation = pretty.indentation - self.group = pretty.group_stack[-1] - self.group.breakables.append(self) - - def output(self, stream, output_width): - self.group.breakables.popleft() - if self.group.want_break: - stream.write(self.pretty.newline) - stream.write(' ' * self.indentation) - return self.indentation - if not self.group.breakables: - self.pretty.group_queue.remove(self.group) - stream.write(self.obj) - return output_width + self.width - - -class Group(Printable): - - def __init__(self, depth): - self.depth = depth - self.breakables = deque() - self.want_break = False - - -class GroupQueue(object): - - def __init__(self, *groups): - self.queue = [] - for group in groups: - self.enq(group) - - def enq(self, group): - depth = group.depth - while depth > len(self.queue) - 1: - self.queue.append([]) - self.queue[depth].append(group) - - def deq(self): - for stack in self.queue: - for idx, group in enumerate(reversed(stack)): - if group.breakables: - del stack[idx] - group.want_break = True - return group - for group in stack: - group.want_break = True - del stack[:] - - def remove(self, group): - try: - self.queue[group.depth].remove(group) - except ValueError: - pass - - -class RawText: - """ Object such that ``p.pretty(RawText(value))`` is the same as ``p.text(value)``. - - An example usage of this would be to show a list as binary numbers, using - ``p.pretty([RawText(bin(i)) for i in integers])``. - """ - def __init__(self, value): - self.value = value - - def _repr_pretty_(self, p, cycle): - p.text(self.value) - - -class CallExpression: - """ Object which emits a line-wrapped call expression in the form `__name(*args, **kwargs)` """ - def __init__(__self, __name, *args, **kwargs): - # dunders are to avoid clashes with kwargs, as python's name manging - # will kick in. - self = __self - self.name = __name - self.args = args - self.kwargs = kwargs - - @classmethod - def factory(cls, name): - def inner(*args, **kwargs): - return cls(name, *args, **kwargs) - return inner - - def _repr_pretty_(self, p, cycle): - # dunders are to avoid clashes with kwargs, as python's name manging - # will kick in. - - started = False - def new_item(): - nonlocal started - if started: - p.text(",") - p.breakable() - started = True - - prefix = self.name + "(" - with p.group(len(prefix), prefix, ")"): - for arg in self.args: - new_item() - p.pretty(arg) - for arg_name, arg in self.kwargs.items(): - new_item() - arg_prefix = arg_name + "=" - with p.group(len(arg_prefix), arg_prefix): - p.pretty(arg) - - -class RawStringLiteral: - """ Wrapper that shows a string with a `r` prefix """ - def __init__(self, value): - self.value = value - - def _repr_pretty_(self, p, cycle): - base_repr = repr(self.value) - if base_repr[:1] in 'uU': - base_repr = base_repr[1:] - prefix = 'ur' - else: - prefix = 'r' - base_repr = prefix + base_repr.replace('\\\\', '\\') - p.text(base_repr) - - -def _default_pprint(obj, p, cycle): - """ - The default print function. Used if an object does not provide one and - it's none of the builtin objects. - """ - klass = _safe_getattr(obj, '__class__', None) or type(obj) - if _safe_getattr(klass, '__repr__', None) is not object.__repr__: - # A user-provided repr. Find newlines and replace them with p.break_() - _repr_pprint(obj, p, cycle) - return - p.begin_group(1, '<') - p.pretty(klass) - p.text(' at 0x%x' % id(obj)) - if cycle: - p.text(' ...') - elif p.verbose: - first = True - for key in dir(obj): - if not key.startswith('_'): - try: - value = getattr(obj, key) - except AttributeError: - continue - if isinstance(value, types.MethodType): - continue - if not first: - p.text(',') - p.breakable() - p.text(key) - p.text('=') - step = len(key) + 1 - p.indentation += step - p.pretty(value) - p.indentation -= step - first = False - p.end_group(1, '>') - - -def _seq_pprinter_factory(start, end): - """ - Factory that returns a pprint function useful for sequences. Used by - the default pprint for tuples and lists. - """ - def inner(obj, p, cycle): - if cycle: - return p.text(start + '...' + end) - step = len(start) - p.begin_group(step, start) - for idx, x in p._enumerate(obj): - if idx: - p.text(',') - p.breakable() - p.pretty(x) - if len(obj) == 1 and isinstance(obj, tuple): - # Special case for 1-item tuples. - p.text(',') - p.end_group(step, end) - return inner - - -def _set_pprinter_factory(start, end): - """ - Factory that returns a pprint function useful for sets and frozensets. - """ - def inner(obj, p, cycle): - if cycle: - return p.text(start + '...' + end) - if len(obj) == 0: - # Special case. - p.text(type(obj).__name__ + '()') - else: - step = len(start) - p.begin_group(step, start) - # Like dictionary keys, we will try to sort the items if there aren't too many - if not (p.max_seq_length and len(obj) >= p.max_seq_length): - items = _sorted_for_pprint(obj) - else: - items = obj - for idx, x in p._enumerate(items): - if idx: - p.text(',') - p.breakable() - p.pretty(x) - p.end_group(step, end) - return inner - - -def _dict_pprinter_factory(start, end): - """ - Factory that returns a pprint function used by the default pprint of - dicts and dict proxies. - """ - def inner(obj, p, cycle): - if cycle: - return p.text('{...}') - step = len(start) - p.begin_group(step, start) - keys = obj.keys() - for idx, key in p._enumerate(keys): - if idx: - p.text(',') - p.breakable() - p.pretty(key) - p.text(': ') - p.pretty(obj[key]) - p.end_group(step, end) - return inner - - -def _super_pprint(obj, p, cycle): - """The pprint for the super type.""" - p.begin_group(8, '<super: ') - 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__) - p.end_group(8, '>') - - - -class _ReFlags: - def __init__(self, value): - self.value = value - - def _repr_pretty_(self, p, cycle): - done_one = False - for flag in ('TEMPLATE', 'IGNORECASE', 'LOCALE', 'MULTILINE', 'DOTALL', - 'UNICODE', 'VERBOSE', 'DEBUG'): - if self.value & getattr(re, flag): - if done_one: - p.text('|') - p.text('re.' + flag) - done_one = True - - -def _re_pattern_pprint(obj, p, cycle): - """The pprint function for regular expression patterns.""" - re_compile = CallExpression.factory('re.compile') - if obj.flags: - p.pretty(re_compile(RawStringLiteral(obj.pattern), _ReFlags(obj.flags))) - else: - p.pretty(re_compile(RawStringLiteral(obj.pattern))) - - -def _types_simplenamespace_pprint(obj, p, cycle): - """The pprint function for types.SimpleNamespace.""" - namespace = CallExpression.factory('namespace') - if cycle: - p.pretty(namespace(RawText("..."))) - else: - p.pretty(namespace(**obj.__dict__)) - - -def _type_pprint(obj, p, cycle): - """The pprint for classes and types.""" - # 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]: - _repr_pprint(obj, p, cycle) - return - - mod = _safe_getattr(obj, '__module__', None) - try: - name = obj.__qualname__ - if not isinstance(name, str): - # This can happen if the type implements __qualname__ as a property - # or other descriptor in Python 2. - raise Exception("Try __name__") - except Exception: - name = obj.__name__ - if not isinstance(name, str): - name = '<unknown type>' - - if mod in (None, '__builtin__', 'builtins', 'exceptions'): - p.text(name) - else: - p.text(mod + '.' + name) - - -def _repr_pprint(obj, p, cycle): - """A pprint that just redirects to the normal repr function.""" - # Find newlines and replace them with p.break_() - output = repr(obj) - lines = output.splitlines() - with p.group(): - for idx, output_line in enumerate(lines): - if idx: - p.break_() - p.text(output_line) - - -def _function_pprint(obj, p, cycle): - """Base pprint for all functions and builtin functions.""" - name = _safe_getattr(obj, '__qualname__', obj.__name__) - mod = obj.__module__ - if mod and mod not in ('__builtin__', 'builtins', 'exceptions'): - name = mod + '.' + name - try: - func_def = name + str(signature(obj)) - except ValueError: - func_def = name - p.text('<function %s>' % func_def) - - -def _exception_pprint(obj, p, cycle): - """Base pprint for all exceptions.""" - name = getattr(obj.__class__, '__qualname__', obj.__class__.__name__) - if obj.__class__.__module__ not in ('exceptions', 'builtins'): - name = '%s.%s' % (obj.__class__.__module__, name) - - p.pretty(CallExpression(name, *getattr(obj, 'args', ()))) - - -#: the exception base -try: - _exception_base = BaseException -except NameError: - _exception_base = Exception - - -#: printers for builtin types -_type_pprinters = { - int: _repr_pprint, - float: _repr_pprint, - str: _repr_pprint, - tuple: _seq_pprinter_factory('(', ')'), - list: _seq_pprinter_factory('[', ']'), - dict: _dict_pprinter_factory('{', '}'), - set: _set_pprinter_factory('{', '}'), - frozenset: _set_pprinter_factory('frozenset({', '})'), - super: _super_pprint, - _re_pattern_type: _re_pattern_pprint, - type: _type_pprint, - types.FunctionType: _function_pprint, - types.BuiltinFunctionType: _function_pprint, - types.MethodType: _repr_pprint, - types.SimpleNamespace: _types_simplenamespace_pprint, - datetime.datetime: _repr_pprint, - datetime.timedelta: _repr_pprint, - _exception_base: _exception_pprint -} - -# render os.environ like a dict -_env_type = type(os.environ) -# future-proof in case os.environ becomes a plain dict? -if _env_type is not dict: - _type_pprinters[_env_type] = _dict_pprinter_factory('environ{', '}') - -try: - # In PyPy, types.DictProxyType is dict, setting the dictproxy printer - # using dict.setdefault avoids overwriting 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[slice] = _repr_pprint - -_type_pprinters[range] = _repr_pprint -_type_pprinters[bytes] = _repr_pprint - -#: printers for types specified by name -_deferred_type_pprinters = { -} - -def for_type(typ, func): - """ - Add a pretty printer for a given type. - """ - oldfunc = _type_pprinters.get(typ, None) - if func is not None: - # To support easy restoration of old pprinters, we need to ignore Nones. - _type_pprinters[typ] = func - return oldfunc - -def for_type_by_name(type_module, type_name, func): - """ - Add a pretty printer for a type specified by the module and name of a type - rather than the type object itself. - """ - key = (type_module, type_name) - oldfunc = _deferred_type_pprinters.get(key, None) - if func is not None: - # To support easy restoration of old pprinters, we need to ignore Nones. - _deferred_type_pprinters[key] = func - return oldfunc - - -#: printers for the default singletons -_singleton_pprinters = dict.fromkeys(map(id, [None, True, False, Ellipsis, - NotImplemented]), _repr_pprint) - - -def _defaultdict_pprint(obj, p, cycle): - cls_ctor = CallExpression.factory(obj.__class__.__name__) - if cycle: - p.pretty(cls_ctor(RawText("..."))) - else: - p.pretty(cls_ctor(obj.default_factory, dict(obj))) - -def _ordereddict_pprint(obj, p, cycle): - cls_ctor = CallExpression.factory(obj.__class__.__name__) - if cycle: - p.pretty(cls_ctor(RawText("..."))) - elif len(obj): - p.pretty(cls_ctor(list(obj.items()))) - else: - p.pretty(cls_ctor()) - -def _deque_pprint(obj, p, cycle): - cls_ctor = CallExpression.factory(obj.__class__.__name__) - if cycle: - p.pretty(cls_ctor(RawText("..."))) - else: - p.pretty(cls_ctor(list(obj))) - -def _counter_pprint(obj, p, cycle): - cls_ctor = CallExpression.factory(obj.__class__.__name__) - if cycle: - p.pretty(cls_ctor(RawText("..."))) - elif len(obj): - p.pretty(cls_ctor(dict(obj))) - else: - p.pretty(cls_ctor()) - - -def _userlist_pprint(obj, p, cycle): - cls_ctor = CallExpression.factory(obj.__class__.__name__) - if cycle: - p.pretty(cls_ctor(RawText("..."))) - else: - p.pretty(cls_ctor(obj.data)) - - -for_type_by_name('collections', 'defaultdict', _defaultdict_pprint) -for_type_by_name('collections', 'OrderedDict', _ordereddict_pprint) -for_type_by_name('collections', 'deque', _deque_pprint) -for_type_by_name('collections', 'Counter', _counter_pprint) -for_type_by_name("collections", "UserList", _userlist_pprint) - -if __name__ == '__main__': - from random import randrange - class Foo(object): - def __init__(self): - self.foo = 1 - self.bar = re.compile(r'\s+') - self.blub = dict.fromkeys(range(30), randrange(1, 40)) - self.hehe = 23424.234234 - self.list = ["blub", "blah", self] - - def get_foo(self): - print("foo") - - pprint(Foo(), verbose=True) diff --git a/contrib/python/ipython/py3/IPython/paths.py b/contrib/python/ipython/py3/IPython/paths.py deleted file mode 100644 index 4fd253cf1e..0000000000 --- a/contrib/python/ipython/py3/IPython/paths.py +++ /dev/null @@ -1,126 +0,0 @@ -"""Find files and directories which IPython uses. -""" -import os.path -import shutil -import tempfile -from warnings import warn - -import IPython -from IPython.utils.importstring import import_item -from IPython.utils.path import ( - get_home_dir, - get_xdg_dir, - get_xdg_cache_dir, - compress_user, - _writable_dir, - ensure_dir_exists, -) - - -def get_ipython_dir() -> str: - """Get the IPython directory for this platform and user. - - This uses the logic in `get_home_dir` to find the home directory - and then adds .ipython to the end of the path. - """ - - env = os.environ - pjoin = os.path.join - - - ipdir_def = '.ipython' - - home_dir = get_home_dir() - xdg_dir = get_xdg_dir() - - if 'IPYTHON_DIR' in env: - warn('The environment variable IPYTHON_DIR is deprecated since IPython 3.0. ' - 'Please use IPYTHONDIR instead.', DeprecationWarning) - ipdir = env.get('IPYTHONDIR', env.get('IPYTHON_DIR', None)) - if ipdir is None: - # not set explicitly, use ~/.ipython - ipdir = pjoin(home_dir, ipdir_def) - if xdg_dir: - # Several IPython versions (up to 1.x) defaulted to .config/ipython - # on Linux. We have decided to go back to using .ipython everywhere - xdg_ipdir = pjoin(xdg_dir, 'ipython') - - if _writable_dir(xdg_ipdir): - cu = compress_user - if os.path.exists(ipdir): - warn(('Ignoring {0} in favour of {1}. Remove {0} to ' - 'get rid of this message').format(cu(xdg_ipdir), cu(ipdir))) - elif os.path.islink(xdg_ipdir): - warn(('{0} is deprecated. Move link to {1} to ' - 'get rid of this message').format(cu(xdg_ipdir), cu(ipdir))) - else: - ipdir = xdg_ipdir - - ipdir = os.path.normpath(os.path.expanduser(ipdir)) - - if os.path.exists(ipdir) and not _writable_dir(ipdir): - # ipdir exists, but is not writable - warn("IPython dir '{0}' is not a writable location," - " using a temp directory.".format(ipdir)) - ipdir = tempfile.mkdtemp() - elif not os.path.exists(ipdir): - parent = os.path.dirname(ipdir) - if not _writable_dir(parent): - # ipdir does not exist and parent isn't writable - warn("IPython parent '{0}' is not a writable location," - " using a temp directory.".format(parent)) - ipdir = tempfile.mkdtemp() - else: - os.makedirs(ipdir, exist_ok=True) - assert isinstance(ipdir, str), "all path manipulation should be str(unicode), but are not." - return ipdir - - -def get_ipython_cache_dir() -> str: - """Get the cache directory it is created if it does not exist.""" - xdgdir = get_xdg_cache_dir() - if xdgdir is None: - return get_ipython_dir() - ipdir = os.path.join(xdgdir, "ipython") - if not os.path.exists(ipdir) and _writable_dir(xdgdir): - ensure_dir_exists(ipdir) - elif not _writable_dir(xdgdir): - return get_ipython_dir() - - return ipdir - - -def get_ipython_package_dir() -> str: - """Get the base directory where IPython itself is installed.""" - ipdir = os.path.dirname(IPython.__file__) - assert isinstance(ipdir, str) - return ipdir - - -def get_ipython_module_path(module_str): - """Find the path to an IPython module in this version of IPython. - - This will always find the version of the module that is in this importable - IPython package. This will always return the path to the ``.py`` - version of the module. - """ - if module_str == 'IPython': - return os.path.join(get_ipython_package_dir(), '__init__.py') - mod = import_item(module_str) - the_path = mod.__file__.replace('.pyc', '.py') - the_path = the_path.replace('.pyo', '.py') - return the_path - - -def locate_profile(profile='default'): - """Find the path to the folder associated with a given profile. - - I.e. find $IPYTHONDIR/profile_whatever. - """ - from IPython.core.profiledir import ProfileDir, ProfileDirError - try: - pd = ProfileDir.find_profile_dir_by_name(get_ipython_dir(), profile) - except ProfileDirError as e: - # IOError makes more sense when people are expecting a path - raise IOError("Couldn't find profile %r" % profile) from e - return pd.location diff --git a/contrib/python/ipython/py3/IPython/sphinxext/__init__.py b/contrib/python/ipython/py3/IPython/sphinxext/__init__.py deleted file mode 100644 index e69de29bb2..0000000000 --- a/contrib/python/ipython/py3/IPython/sphinxext/__init__.py +++ /dev/null diff --git a/contrib/python/ipython/py3/IPython/sphinxext/custom_doctests.py b/contrib/python/ipython/py3/IPython/sphinxext/custom_doctests.py deleted file mode 100644 index 75c2a25ccb..0000000000 --- a/contrib/python/ipython/py3/IPython/sphinxext/custom_doctests.py +++ /dev/null @@ -1,155 +0,0 @@ -""" -Handlers for IPythonDirective's @doctest pseudo-decorator. - -The Sphinx extension that provides support for embedded IPython code provides -a pseudo-decorator @doctest, which treats the input/output block as a -doctest, raising a RuntimeError during doc generation if the actual output -(after running the input) does not match the expected output. - -An example usage is: - -.. code-block:: rst - - .. ipython:: - - In [1]: x = 1 - - @doctest - In [2]: x + 2 - Out[3]: 3 - -One can also provide arguments to the decorator. The first argument should be -the name of a custom handler. The specification of any other arguments is -determined by the handler. For example, - -.. code-block:: rst - - .. ipython:: - - @doctest float - In [154]: 0.1 + 0.2 - Out[154]: 0.3 - -allows the actual output ``0.30000000000000004`` to match the expected output -due to a comparison with `np.allclose`. - -This module contains handlers for the @doctest pseudo-decorator. Handlers -should have the following function signature:: - - handler(sphinx_shell, args, input_lines, found, submitted) - -where `sphinx_shell` is the embedded Sphinx shell, `args` contains the list -of arguments that follow: '@doctest handler_name', `input_lines` contains -a list of the lines relevant to the current doctest, `found` is a string -containing the output from the IPython shell, and `submitted` is a string -containing the expected output from the IPython shell. - -Handlers must be registered in the `doctests` dict at the end of this module. - -""" - -def str_to_array(s): - """ - Simplistic converter of strings from repr to float NumPy arrays. - - If the repr representation has ellipsis in it, then this will fail. - - Parameters - ---------- - s : str - The repr version of a NumPy array. - - Examples - -------- - >>> s = "array([ 0.3, inf, nan])" - >>> a = str_to_array(s) - - """ - import numpy as np - - # Need to make sure eval() knows about inf and nan. - # This also assumes default printoptions for NumPy. - from numpy import inf, nan - - if s.startswith(u'array'): - # Remove array( and ) - s = s[6:-1] - - if s.startswith(u'['): - a = np.array(eval(s), dtype=float) - else: - # Assume its a regular float. Force 1D so we can index into it. - a = np.atleast_1d(float(s)) - return a - -def float_doctest(sphinx_shell, args, input_lines, found, submitted): - """ - Doctest which allow the submitted output to vary slightly from the input. - - Here is how it might appear in an rst file: - - .. code-block:: rst - - .. ipython:: - - @doctest float - In [1]: 0.1 + 0.2 - Out[1]: 0.3 - - """ - import numpy as np - - if len(args) == 2: - rtol = 1e-05 - atol = 1e-08 - else: - # Both must be specified if any are specified. - try: - rtol = float(args[2]) - atol = float(args[3]) - except IndexError as e: - e = ("Both `rtol` and `atol` must be specified " - "if either are specified: {0}".format(args)) - raise IndexError(e) from e - - try: - submitted = str_to_array(submitted) - found = str_to_array(found) - except: - # For example, if the array is huge and there are ellipsis in it. - error = True - else: - found_isnan = np.isnan(found) - submitted_isnan = np.isnan(submitted) - error = not np.allclose(found_isnan, submitted_isnan) - error |= not np.allclose(found[~found_isnan], - submitted[~submitted_isnan], - rtol=rtol, atol=atol) - - TAB = ' ' * 4 - directive = sphinx_shell.directive - if directive is None: - source = 'Unavailable' - content = 'Unavailable' - else: - source = directive.state.document.current_source - # Add tabs and make into a single string. - content = '\n'.join([TAB + line for line in directive.content]) - - if error: - - e = ('doctest float comparison failure\n\n' - 'Document source: {0}\n\n' - 'Raw content: \n{1}\n\n' - 'On input line(s):\n{TAB}{2}\n\n' - 'we found output:\n{TAB}{3}\n\n' - 'instead of the expected:\n{TAB}{4}\n\n') - e = e.format(source, content, '\n'.join(input_lines), repr(found), - repr(submitted), TAB=TAB) - raise RuntimeError(e) - -# dict of allowable doctest handlers. The key represents the first argument -# that must be given to @doctest in order to activate the handler. -doctests = { - 'float': float_doctest, -} diff --git a/contrib/python/ipython/py3/IPython/sphinxext/ipython_console_highlighting.py b/contrib/python/ipython/py3/IPython/sphinxext/ipython_console_highlighting.py deleted file mode 100644 index b93a151fb3..0000000000 --- a/contrib/python/ipython/py3/IPython/sphinxext/ipython_console_highlighting.py +++ /dev/null @@ -1,28 +0,0 @@ -""" -reST directive for syntax-highlighting ipython interactive sessions. - -""" - -from sphinx import highlighting -from IPython.lib.lexers import IPyLexer - -def setup(app): - """Setup as a sphinx extension.""" - - # This is only a lexer, so adding it below to pygments appears sufficient. - # But if somebody knows what the right API usage should be to do that via - # sphinx, by all means fix it here. At least having this setup.py - # suppresses the sphinx warning we'd get without it. - metadata = {'parallel_read_safe': True, 'parallel_write_safe': True} - return metadata - -# Register the extension as a valid pygments lexer. -# Alternatively, we could register the lexer with pygments instead. This would -# require using setuptools entrypoints: http://pygments.org/docs/plugins - -ipy2 = IPyLexer(python3=False) -ipy3 = IPyLexer(python3=True) - -highlighting.lexers['ipython'] = ipy2 -highlighting.lexers['ipython2'] = ipy2 -highlighting.lexers['ipython3'] = ipy3 diff --git a/contrib/python/ipython/py3/IPython/sphinxext/ipython_directive.py b/contrib/python/ipython/py3/IPython/sphinxext/ipython_directive.py deleted file mode 100644 index 18bdfcae99..0000000000 --- a/contrib/python/ipython/py3/IPython/sphinxext/ipython_directive.py +++ /dev/null @@ -1,1268 +0,0 @@ -# -*- coding: utf-8 -*- -""" -Sphinx directive to support embedded IPython code. - -IPython provides an extension for `Sphinx <http://www.sphinx-doc.org/>`_ to -highlight and run code. - -This directive allows pasting of entire interactive IPython sessions, prompts -and all, and their code will actually get re-executed at doc build time, with -all prompts renumbered sequentially. It also allows you to input code as a pure -python input by giving the argument python to the directive. The output looks -like an interactive ipython section. - -Here is an example of how the IPython directive can -**run** python code, at build time. - -.. ipython:: - - In [1]: 1+1 - - In [1]: import datetime - ...: datetime.datetime.now() - -It supports IPython construct that plain -Python does not understand (like magics): - -.. ipython:: - - In [0]: import time - - In [0]: %timeit time.sleep(0.05) - -This will also support top-level async when using IPython 7.0+ - -.. ipython:: - - In [2]: import asyncio - ...: print('before') - ...: await asyncio.sleep(1) - ...: print('after') - - -The namespace will persist across multiple code chucks, Let's define a variable: - -.. ipython:: - - In [0]: who = "World" - -And now say hello: - -.. ipython:: - - In [0]: print('Hello,', who) - -If the current section raises an exception, you can add the ``:okexcept:`` flag -to the current block, otherwise the build will fail. - -.. ipython:: - :okexcept: - - In [1]: 1/0 - -IPython Sphinx directive module -=============================== - -To enable this directive, simply list it in your Sphinx ``conf.py`` file -(making sure the directory where you placed it is visible to sphinx, as is -needed for all Sphinx directives). For example, to enable syntax highlighting -and the IPython directive:: - - extensions = ['IPython.sphinxext.ipython_console_highlighting', - 'IPython.sphinxext.ipython_directive'] - -The IPython directive outputs code-blocks with the language 'ipython'. So -if you do not have the syntax highlighting extension enabled as well, then -all rendered code-blocks will be uncolored. By default this directive assumes -that your prompts are unchanged IPython ones, but this can be customized. -The configurable options that can be placed in conf.py are: - -ipython_savefig_dir: - The directory in which to save the figures. This is relative to the - Sphinx source directory. The default is `html_static_path`. -ipython_rgxin: - The compiled regular expression to denote the start of IPython input - lines. The default is ``re.compile('In \\[(\\d+)\\]:\\s?(.*)\\s*')``. You - shouldn't need to change this. -ipython_warning_is_error: [default to True] - Fail the build if something unexpected happen, for example if a block raise - an exception but does not have the `:okexcept:` flag. The exact behavior of - what is considered strict, may change between the sphinx directive version. -ipython_rgxout: - The compiled regular expression to denote the start of IPython output - lines. The default is ``re.compile('Out\\[(\\d+)\\]:\\s?(.*)\\s*')``. You - shouldn't need to change this. -ipython_promptin: - The string to represent the IPython input prompt in the generated ReST. - The default is ``'In [%d]:'``. This expects that the line numbers are used - in the prompt. -ipython_promptout: - The string to represent the IPython prompt in the generated ReST. The - default is ``'Out [%d]:'``. This expects that the line numbers are used - in the prompt. -ipython_mplbackend: - The string which specifies if the embedded Sphinx shell should import - Matplotlib and set the backend. The value specifies a backend that is - passed to `matplotlib.use()` before any lines in `ipython_execlines` are - executed. If not specified in conf.py, then the default value of 'agg' is - used. To use the IPython directive without matplotlib as a dependency, set - the value to `None`. It may end up that matplotlib is still imported - if the user specifies so in `ipython_execlines` or makes use of the - @savefig pseudo decorator. -ipython_execlines: - A list of strings to be exec'd in the embedded Sphinx shell. Typical - usage is to make certain packages always available. Set this to an empty - list if you wish to have no imports always available. If specified in - ``conf.py`` as `None`, then it has the effect of making no imports available. - If omitted from conf.py altogether, then the default value of - ['import numpy as np', 'import matplotlib.pyplot as plt'] is used. -ipython_holdcount - When the @suppress pseudo-decorator is used, the execution count can be - incremented or not. The default behavior is to hold the execution count, - corresponding to a value of `True`. Set this to `False` to increment - the execution count after each suppressed command. - -As an example, to use the IPython directive when `matplotlib` is not available, -one sets the backend to `None`:: - - ipython_mplbackend = None - -An example usage of the directive is: - -.. code-block:: rst - - .. ipython:: - - In [1]: x = 1 - - In [2]: y = x**2 - - In [3]: print(y) - -See http://matplotlib.org/sampledoc/ipython_directive.html for additional -documentation. - -Pseudo-Decorators -================= - -Note: Only one decorator is supported per input. If more than one decorator -is specified, then only the last one is used. - -In addition to the Pseudo-Decorators/options described at the above link, -several enhancements have been made. The directive will emit a message to the -console at build-time if code-execution resulted in an exception or warning. -You can suppress these on a per-block basis by specifying the :okexcept: -or :okwarning: options: - -.. code-block:: rst - - .. ipython:: - :okexcept: - :okwarning: - - In [1]: 1/0 - In [2]: # raise warning. - -To Do -===== - -- Turn the ad-hoc test() function into a real test suite. -- Break up ipython-specific functionality from matplotlib stuff into better - separated code. - -""" - -# Authors -# ======= -# -# - John D Hunter: original author. -# - Fernando Perez: refactoring, documentation, cleanups, port to 0.11. -# - VáclavŠmilauer <eudoxos-AT-arcig.cz>: Prompt generalizations. -# - Skipper Seabold, refactoring, cleanups, pure python addition - -#----------------------------------------------------------------------------- -# Imports -#----------------------------------------------------------------------------- - -# Stdlib -import atexit -import errno -import os -import pathlib -import re -import sys -import tempfile -import ast -import warnings -import shutil -from io import StringIO - -# Third-party -from docutils.parsers.rst import directives -from docutils.parsers.rst import Directive -from sphinx.util import logging - -# Our own -from traitlets.config import Config -from IPython import InteractiveShell -from IPython.core.profiledir import ProfileDir - -use_matplotlib = False -try: - import matplotlib - use_matplotlib = True -except Exception: - pass - -#----------------------------------------------------------------------------- -# Globals -#----------------------------------------------------------------------------- -# for tokenizing blocks -COMMENT, INPUT, OUTPUT = range(3) - -PSEUDO_DECORATORS = ["suppress", "verbatim", "savefig", "doctest"] - -#----------------------------------------------------------------------------- -# Functions and class declarations -#----------------------------------------------------------------------------- - -def block_parser(part, rgxin, rgxout, fmtin, fmtout): - """ - part is a string of ipython text, comprised of at most one - input, one output, comments, and blank lines. The block parser - parses the text into a list of:: - - blocks = [ (TOKEN0, data0), (TOKEN1, data1), ...] - - where TOKEN is one of [COMMENT | INPUT | OUTPUT ] and - data is, depending on the type of token:: - - COMMENT : the comment string - - INPUT: the (DECORATOR, INPUT_LINE, REST) where - DECORATOR: the input decorator (or None) - INPUT_LINE: the input as string (possibly multi-line) - REST : any stdout generated by the input line (not OUTPUT) - - OUTPUT: the output string, possibly multi-line - - """ - block = [] - lines = part.split('\n') - N = len(lines) - i = 0 - decorator = None - while 1: - - if i==N: - # nothing left to parse -- the last line - break - - line = lines[i] - i += 1 - line_stripped = line.strip() - if line_stripped.startswith('#'): - block.append((COMMENT, line)) - continue - - if any( - line_stripped.startswith("@" + pseudo_decorator) - for pseudo_decorator in PSEUDO_DECORATORS - ): - if decorator: - raise RuntimeError( - "Applying multiple pseudo-decorators on one line is not supported" - ) - else: - decorator = line_stripped - continue - - # does this look like an input line? - matchin = rgxin.match(line) - if matchin: - lineno, inputline = int(matchin.group(1)), matchin.group(2) - - # the ....: continuation string - continuation = ' %s:'%''.join(['.']*(len(str(lineno))+2)) - Nc = len(continuation) - # input lines can continue on for more than one line, if - # we have a '\' line continuation char or a function call - # echo line 'print'. The input line can only be - # terminated by the end of the block or an output line, so - # we parse out the rest of the input line if it is - # multiline as well as any echo text - - rest = [] - while i<N: - - # look ahead; if the next line is blank, or a comment, or - # an output line, we're done - - nextline = lines[i] - matchout = rgxout.match(nextline) - #print "nextline=%s, continuation=%s, starts=%s"%(nextline, continuation, nextline.startswith(continuation)) - if matchout or nextline.startswith('#'): - break - elif nextline.startswith(continuation): - # The default ipython_rgx* treat the space following the colon as optional. - # However, If the space is there we must consume it or code - # employing the cython_magic extension will fail to execute. - # - # This works with the default ipython_rgx* patterns, - # If you modify them, YMMV. - nextline = nextline[Nc:] - if nextline and nextline[0] == ' ': - nextline = nextline[1:] - - inputline += '\n' + nextline - else: - rest.append(nextline) - i+= 1 - - block.append((INPUT, (decorator, inputline, '\n'.join(rest)))) - continue - - # if it looks like an output line grab all the text to the end - # of the block - matchout = rgxout.match(line) - if matchout: - lineno, output = int(matchout.group(1)), matchout.group(2) - if i<N-1: - output = '\n'.join([output] + lines[i:]) - - block.append((OUTPUT, output)) - break - - return block - - -class EmbeddedSphinxShell(object): - """An embedded IPython instance to run inside Sphinx""" - - def __init__(self, exec_lines=None): - - self.cout = StringIO() - - if exec_lines is None: - exec_lines = [] - - # Create config object for IPython - config = Config() - config.HistoryManager.hist_file = ':memory:' - config.InteractiveShell.autocall = False - config.InteractiveShell.autoindent = False - config.InteractiveShell.colors = 'NoColor' - - # create a profile so instance history isn't saved - tmp_profile_dir = tempfile.mkdtemp(prefix='profile_') - profname = 'auto_profile_sphinx_build' - pdir = os.path.join(tmp_profile_dir,profname) - profile = ProfileDir.create_profile_dir(pdir) - - # Create and initialize global ipython, but don't start its mainloop. - # This will persist across different EmbeddedSphinxShell instances. - IP = InteractiveShell.instance(config=config, profile_dir=profile) - atexit.register(self.cleanup) - - # Store a few parts of IPython we'll need. - self.IP = IP - self.user_ns = self.IP.user_ns - self.user_global_ns = self.IP.user_global_ns - - self.input = '' - self.output = '' - self.tmp_profile_dir = tmp_profile_dir - - self.is_verbatim = False - self.is_doctest = False - self.is_suppress = False - - # Optionally, provide more detailed information to shell. - # this is assigned by the SetUp method of IPythonDirective - # to point at itself. - # - # So, you can access handy things at self.directive.state - self.directive = None - - # on the first call to the savefig decorator, we'll import - # pyplot as plt so we can make a call to the plt.gcf().savefig - self._pyplot_imported = False - - # Prepopulate the namespace. - for line in exec_lines: - self.process_input_line(line, store_history=False) - - def cleanup(self): - shutil.rmtree(self.tmp_profile_dir, ignore_errors=True) - - def clear_cout(self): - self.cout.seek(0) - self.cout.truncate(0) - - def process_input_line(self, line, store_history): - return self.process_input_lines([line], store_history=store_history) - - def process_input_lines(self, lines, store_history=True): - """process the input, capturing stdout""" - stdout = sys.stdout - source_raw = '\n'.join(lines) - try: - sys.stdout = self.cout - self.IP.run_cell(source_raw, store_history=store_history) - finally: - sys.stdout = stdout - - def process_image(self, decorator): - """ - # build out an image directive like - # .. image:: somefile.png - # :width 4in - # - # from an input like - # savefig somefile.png width=4in - """ - savefig_dir = self.savefig_dir - source_dir = self.source_dir - saveargs = decorator.split(' ') - filename = saveargs[1] - # insert relative path to image file in source - # as absolute path for Sphinx - # sphinx expects a posix path, even on Windows - path = pathlib.Path(savefig_dir, filename) - outfile = '/' + path.relative_to(source_dir).as_posix() - - imagerows = ['.. image:: %s' % outfile] - - for kwarg in saveargs[2:]: - arg, val = kwarg.split('=') - arg = arg.strip() - val = val.strip() - imagerows.append(' :%s: %s'%(arg, val)) - - image_file = os.path.basename(outfile) # only return file name - image_directive = '\n'.join(imagerows) - return image_file, image_directive - - # Callbacks for each type of token - def process_input(self, data, input_prompt, lineno): - """ - Process data block for INPUT token. - - """ - decorator, input, rest = data - image_file = None - image_directive = None - - is_verbatim = decorator=='@verbatim' or self.is_verbatim - is_doctest = (decorator is not None and \ - decorator.startswith('@doctest')) or self.is_doctest - is_suppress = decorator=='@suppress' or self.is_suppress - is_okexcept = decorator=='@okexcept' or self.is_okexcept - is_okwarning = decorator=='@okwarning' or self.is_okwarning - is_savefig = decorator is not None and \ - decorator.startswith('@savefig') - - input_lines = input.split('\n') - if len(input_lines) > 1: - if input_lines[-1] != "": - input_lines.append('') # make sure there's a blank line - # so splitter buffer gets reset - - continuation = ' %s:'%''.join(['.']*(len(str(lineno))+2)) - - if is_savefig: - image_file, image_directive = self.process_image(decorator) - - ret = [] - is_semicolon = False - - # Hold the execution count, if requested to do so. - if is_suppress and self.hold_count: - store_history = False - else: - store_history = True - - # Note: catch_warnings is not thread safe - with warnings.catch_warnings(record=True) as ws: - if input_lines[0].endswith(';'): - is_semicolon = True - #for i, line in enumerate(input_lines): - - # process the first input line - if is_verbatim: - self.process_input_lines(['']) - self.IP.execution_count += 1 # increment it anyway - else: - # only submit the line in non-verbatim mode - self.process_input_lines(input_lines, store_history=store_history) - - if not is_suppress: - for i, line in enumerate(input_lines): - if i == 0: - formatted_line = '%s %s'%(input_prompt, line) - else: - formatted_line = '%s %s'%(continuation, line) - ret.append(formatted_line) - - if not is_suppress and len(rest.strip()) and is_verbatim: - # The "rest" is the standard output of the input. This needs to be - # added when in verbatim mode. If there is no "rest", then we don't - # add it, as the new line will be added by the processed output. - ret.append(rest) - - # Fetch the processed output. (This is not the submitted output.) - self.cout.seek(0) - processed_output = self.cout.read() - if not is_suppress and not is_semicolon: - # - # In IPythonDirective.run, the elements of `ret` are eventually - # combined such that '' entries correspond to newlines. So if - # `processed_output` is equal to '', then the adding it to `ret` - # ensures that there is a blank line between consecutive inputs - # that have no outputs, as in: - # - # In [1]: x = 4 - # - # In [2]: x = 5 - # - # When there is processed output, it has a '\n' at the tail end. So - # adding the output to `ret` will provide the necessary spacing - # between consecutive input/output blocks, as in: - # - # In [1]: x - # Out[1]: 5 - # - # In [2]: x - # Out[2]: 5 - # - # When there is stdout from the input, it also has a '\n' at the - # tail end, and so this ensures proper spacing as well. E.g.: - # - # In [1]: print x - # 5 - # - # In [2]: x = 5 - # - # When in verbatim mode, `processed_output` is empty (because - # nothing was passed to IP. Sometimes the submitted code block has - # an Out[] portion and sometimes it does not. When it does not, we - # need to ensure proper spacing, so we have to add '' to `ret`. - # However, if there is an Out[] in the submitted code, then we do - # not want to add a newline as `process_output` has stuff to add. - # The difficulty is that `process_input` doesn't know if - # `process_output` will be called---so it doesn't know if there is - # Out[] in the code block. The requires that we include a hack in - # `process_block`. See the comments there. - # - ret.append(processed_output) - elif is_semicolon: - # Make sure there is a newline after the semicolon. - ret.append('') - - # context information - filename = "Unknown" - lineno = 0 - if self.directive.state: - filename = self.directive.state.document.current_source - lineno = self.directive.state.document.current_line - - # Use sphinx logger for warnings - logger = logging.getLogger(__name__) - - # output any exceptions raised during execution to stdout - # unless :okexcept: has been specified. - if not is_okexcept and ( - ("Traceback" in processed_output) or ("SyntaxError" in processed_output) - ): - s = "\n>>>" + ("-" * 73) + "\n" - s += "Exception in %s at block ending on line %s\n" % (filename, lineno) - s += "Specify :okexcept: as an option in the ipython:: block to suppress this message\n" - s += processed_output + "\n" - s += "<<<" + ("-" * 73) - logger.warning(s) - if self.warning_is_error: - raise RuntimeError('Non Expected exception in `{}` line {}'.format(filename, lineno)) - - # output any warning raised during execution to stdout - # unless :okwarning: has been specified. - if not is_okwarning: - for w in ws: - s = "\n>>>" + ("-" * 73) + "\n" - s += "Warning in %s at block ending on line %s\n" % (filename, lineno) - s += "Specify :okwarning: as an option in the ipython:: block to suppress this message\n" - s += ("-" * 76) + "\n" - s += warnings.formatwarning( - w.message, w.category, w.filename, w.lineno, w.line - ) - s += "<<<" + ("-" * 73) - logger.warning(s) - if self.warning_is_error: - raise RuntimeError('Non Expected warning in `{}` line {}'.format(filename, lineno)) - - self.clear_cout() - return (ret, input_lines, processed_output, - is_doctest, decorator, image_file, image_directive) - - - def process_output(self, data, output_prompt, input_lines, output, - is_doctest, decorator, image_file): - """ - Process data block for OUTPUT token. - - """ - # Recall: `data` is the submitted output, and `output` is the processed - # output from `input_lines`. - - TAB = ' ' * 4 - - if is_doctest and output is not None: - - found = output # This is the processed output - found = found.strip() - submitted = data.strip() - - if self.directive is None: - source = 'Unavailable' - content = 'Unavailable' - else: - source = self.directive.state.document.current_source - content = self.directive.content - # Add tabs and join into a single string. - content = '\n'.join([TAB + line for line in content]) - - # Make sure the output contains the output prompt. - ind = found.find(output_prompt) - if ind < 0: - e = ('output does not contain output prompt\n\n' - 'Document source: {0}\n\n' - 'Raw content: \n{1}\n\n' - 'Input line(s):\n{TAB}{2}\n\n' - 'Output line(s):\n{TAB}{3}\n\n') - e = e.format(source, content, '\n'.join(input_lines), - repr(found), TAB=TAB) - raise RuntimeError(e) - found = found[len(output_prompt):].strip() - - # Handle the actual doctest comparison. - if decorator.strip() == '@doctest': - # Standard doctest - if found != submitted: - e = ('doctest failure\n\n' - 'Document source: {0}\n\n' - 'Raw content: \n{1}\n\n' - 'On input line(s):\n{TAB}{2}\n\n' - 'we found output:\n{TAB}{3}\n\n' - 'instead of the expected:\n{TAB}{4}\n\n') - e = e.format(source, content, '\n'.join(input_lines), - repr(found), repr(submitted), TAB=TAB) - raise RuntimeError(e) - else: - self.custom_doctest(decorator, input_lines, found, submitted) - - # When in verbatim mode, this holds additional submitted output - # to be written in the final Sphinx output. - # https://github.com/ipython/ipython/issues/5776 - out_data = [] - - is_verbatim = decorator=='@verbatim' or self.is_verbatim - if is_verbatim and data.strip(): - # Note that `ret` in `process_block` has '' as its last element if - # the code block was in verbatim mode. So if there is no submitted - # output, then we will have proper spacing only if we do not add - # an additional '' to `out_data`. This is why we condition on - # `and data.strip()`. - - # The submitted output has no output prompt. If we want the - # prompt and the code to appear, we need to join them now - # instead of adding them separately---as this would create an - # undesired newline. How we do this ultimately depends on the - # format of the output regex. I'll do what works for the default - # prompt for now, and we might have to adjust if it doesn't work - # in other cases. Finally, the submitted output does not have - # a trailing newline, so we must add it manually. - out_data.append("{0} {1}\n".format(output_prompt, data)) - - return out_data - - def process_comment(self, data): - """Process data fPblock for COMMENT token.""" - if not self.is_suppress: - return [data] - - def save_image(self, image_file): - """ - Saves the image file to disk. - """ - self.ensure_pyplot() - command = 'plt.gcf().savefig("%s")'%image_file - #print 'SAVEFIG', command # dbg - self.process_input_line('bookmark ipy_thisdir', store_history=False) - self.process_input_line('cd -b ipy_savedir', store_history=False) - self.process_input_line(command, store_history=False) - self.process_input_line('cd -b ipy_thisdir', store_history=False) - self.process_input_line('bookmark -d ipy_thisdir', store_history=False) - self.clear_cout() - - def process_block(self, block): - """ - process block from the block_parser and return a list of processed lines - """ - ret = [] - output = None - input_lines = None - lineno = self.IP.execution_count - - input_prompt = self.promptin % lineno - output_prompt = self.promptout % lineno - image_file = None - image_directive = None - - found_input = False - for token, data in block: - if token == COMMENT: - out_data = self.process_comment(data) - elif token == INPUT: - found_input = True - (out_data, input_lines, output, is_doctest, - decorator, image_file, image_directive) = \ - self.process_input(data, input_prompt, lineno) - elif token == OUTPUT: - if not found_input: - - TAB = ' ' * 4 - linenumber = 0 - source = 'Unavailable' - content = 'Unavailable' - if self.directive: - linenumber = self.directive.state.document.current_line - source = self.directive.state.document.current_source - content = self.directive.content - # Add tabs and join into a single string. - content = '\n'.join([TAB + line for line in content]) - - e = ('\n\nInvalid block: Block contains an output prompt ' - 'without an input prompt.\n\n' - 'Document source: {0}\n\n' - 'Content begins at line {1}: \n\n{2}\n\n' - 'Problematic block within content: \n\n{TAB}{3}\n\n') - e = e.format(source, linenumber, content, block, TAB=TAB) - - # Write, rather than include in exception, since Sphinx - # will truncate tracebacks. - sys.stdout.write(e) - raise RuntimeError('An invalid block was detected.') - out_data = \ - self.process_output(data, output_prompt, input_lines, - output, is_doctest, decorator, - image_file) - if out_data: - # Then there was user submitted output in verbatim mode. - # We need to remove the last element of `ret` that was - # added in `process_input`, as it is '' and would introduce - # an undesirable newline. - assert(ret[-1] == '') - del ret[-1] - - if out_data: - ret.extend(out_data) - - # save the image files - if image_file is not None: - self.save_image(image_file) - - return ret, image_directive - - def ensure_pyplot(self): - """ - Ensures that pyplot has been imported into the embedded IPython shell. - - Also, makes sure to set the backend appropriately if not set already. - - """ - # We are here if the @figure pseudo decorator was used. Thus, it's - # possible that we could be here even if python_mplbackend were set to - # `None`. That's also strange and perhaps worthy of raising an - # exception, but for now, we just set the backend to 'agg'. - - if not self._pyplot_imported: - if 'matplotlib.backends' not in sys.modules: - # Then ipython_matplotlib was set to None but there was a - # call to the @figure decorator (and ipython_execlines did - # not set a backend). - #raise Exception("No backend was set, but @figure was used!") - import matplotlib - matplotlib.use('agg') - - # Always import pyplot into embedded shell. - self.process_input_line('import matplotlib.pyplot as plt', - store_history=False) - self._pyplot_imported = True - - def process_pure_python(self, content): - """ - content is a list of strings. it is unedited directive content - - This runs it line by line in the InteractiveShell, prepends - prompts as needed capturing stderr and stdout, then returns - the content as a list as if it were ipython code - """ - output = [] - savefig = False # keep up with this to clear figure - multiline = False # to handle line continuation - multiline_start = None - fmtin = self.promptin - - ct = 0 - - for lineno, line in enumerate(content): - - line_stripped = line.strip() - if not len(line): - output.append(line) - continue - - # handle decorators - if line_stripped.startswith('@'): - output.extend([line]) - if 'savefig' in line: - savefig = True # and need to clear figure - continue - - # handle comments - if line_stripped.startswith('#'): - output.extend([line]) - continue - - # deal with lines checking for multiline - continuation = u' %s:'% ''.join(['.']*(len(str(ct))+2)) - if not multiline: - modified = u"%s %s" % (fmtin % ct, line_stripped) - output.append(modified) - ct += 1 - try: - ast.parse(line_stripped) - output.append(u'') - except Exception: # on a multiline - multiline = True - multiline_start = lineno - else: # still on a multiline - modified = u'%s %s' % (continuation, line) - output.append(modified) - - # if the next line is indented, it should be part of multiline - if len(content) > lineno + 1: - nextline = content[lineno + 1] - if len(nextline) - len(nextline.lstrip()) > 3: - continue - try: - mod = ast.parse( - '\n'.join(content[multiline_start:lineno+1])) - if isinstance(mod.body[0], ast.FunctionDef): - # check to see if we have the whole function - for element in mod.body[0].body: - if isinstance(element, ast.Return): - multiline = False - else: - output.append(u'') - multiline = False - except Exception: - pass - - if savefig: # clear figure if plotted - self.ensure_pyplot() - self.process_input_line('plt.clf()', store_history=False) - self.clear_cout() - savefig = False - - return output - - def custom_doctest(self, decorator, input_lines, found, submitted): - """ - Perform a specialized doctest. - - """ - from .custom_doctests import doctests - - args = decorator.split() - doctest_type = args[1] - if doctest_type in doctests: - doctests[doctest_type](self, args, input_lines, found, submitted) - else: - e = "Invalid option to @doctest: {0}".format(doctest_type) - raise Exception(e) - - -class IPythonDirective(Directive): - - has_content = True - required_arguments = 0 - optional_arguments = 4 # python, suppress, verbatim, doctest - final_argumuent_whitespace = True - option_spec = { 'python': directives.unchanged, - 'suppress' : directives.flag, - 'verbatim' : directives.flag, - 'doctest' : directives.flag, - 'okexcept': directives.flag, - 'okwarning': directives.flag - } - - shell = None - - seen_docs = set() - - def get_config_options(self): - # contains sphinx configuration variables - config = self.state.document.settings.env.config - - # get config variables to set figure output directory - savefig_dir = config.ipython_savefig_dir - source_dir = self.state.document.settings.env.srcdir - savefig_dir = os.path.join(source_dir, savefig_dir) - - # get regex and prompt stuff - rgxin = config.ipython_rgxin - rgxout = config.ipython_rgxout - warning_is_error= config.ipython_warning_is_error - promptin = config.ipython_promptin - promptout = config.ipython_promptout - mplbackend = config.ipython_mplbackend - exec_lines = config.ipython_execlines - hold_count = config.ipython_holdcount - - return (savefig_dir, source_dir, rgxin, rgxout, - promptin, promptout, mplbackend, exec_lines, hold_count, warning_is_error) - - def setup(self): - # Get configuration values. - (savefig_dir, source_dir, rgxin, rgxout, promptin, promptout, - mplbackend, exec_lines, hold_count, warning_is_error) = self.get_config_options() - - try: - os.makedirs(savefig_dir) - except OSError as e: - if e.errno != errno.EEXIST: - raise - - if self.shell is None: - # We will be here many times. However, when the - # EmbeddedSphinxShell is created, its interactive shell member - # is the same for each instance. - - if mplbackend and 'matplotlib.backends' not in sys.modules and use_matplotlib: - import matplotlib - matplotlib.use(mplbackend) - - # Must be called after (potentially) importing matplotlib and - # setting its backend since exec_lines might import pylab. - self.shell = EmbeddedSphinxShell(exec_lines) - - # Store IPython directive to enable better error messages - self.shell.directive = self - - # reset the execution count if we haven't processed this doc - #NOTE: this may be borked if there are multiple seen_doc tmp files - #check time stamp? - if not self.state.document.current_source in self.seen_docs: - self.shell.IP.history_manager.reset() - self.shell.IP.execution_count = 1 - self.seen_docs.add(self.state.document.current_source) - - # and attach to shell so we don't have to pass them around - self.shell.rgxin = rgxin - self.shell.rgxout = rgxout - self.shell.promptin = promptin - self.shell.promptout = promptout - self.shell.savefig_dir = savefig_dir - self.shell.source_dir = source_dir - self.shell.hold_count = hold_count - self.shell.warning_is_error = warning_is_error - - # setup bookmark for saving figures directory - self.shell.process_input_line('bookmark ipy_savedir %s'%savefig_dir, - store_history=False) - self.shell.clear_cout() - - return rgxin, rgxout, promptin, promptout - - def teardown(self): - # delete last bookmark - self.shell.process_input_line('bookmark -d ipy_savedir', - store_history=False) - self.shell.clear_cout() - - def run(self): - debug = False - - #TODO, any reason block_parser can't be a method of embeddable shell - # then we wouldn't have to carry these around - rgxin, rgxout, promptin, promptout = self.setup() - - options = self.options - self.shell.is_suppress = 'suppress' in options - self.shell.is_doctest = 'doctest' in options - self.shell.is_verbatim = 'verbatim' in options - self.shell.is_okexcept = 'okexcept' in options - self.shell.is_okwarning = 'okwarning' in options - - # handle pure python code - if 'python' in self.arguments: - content = self.content - self.content = self.shell.process_pure_python(content) - - # parts consists of all text within the ipython-block. - # Each part is an input/output block. - parts = '\n'.join(self.content).split('\n\n') - - lines = ['.. code-block:: ipython', ''] - figures = [] - - # Use sphinx logger for warnings - logger = logging.getLogger(__name__) - - for part in parts: - block = block_parser(part, rgxin, rgxout, promptin, promptout) - if len(block): - rows, figure = self.shell.process_block(block) - for row in rows: - lines.extend([' {0}'.format(line) - for line in row.split('\n')]) - - if figure is not None: - figures.append(figure) - else: - message = 'Code input with no code at {}, line {}'\ - .format( - self.state.document.current_source, - self.state.document.current_line) - if self.shell.warning_is_error: - raise RuntimeError(message) - else: - logger.warning(message) - - for figure in figures: - lines.append('') - lines.extend(figure.split('\n')) - lines.append('') - - if len(lines) > 2: - if debug: - print('\n'.join(lines)) - else: - # This has to do with input, not output. But if we comment - # these lines out, then no IPython code will appear in the - # final output. - self.state_machine.insert_input( - lines, self.state_machine.input_lines.source(0)) - - # cleanup - self.teardown() - - return [] - -# Enable as a proper Sphinx directive -def setup(app): - setup.app = app - - app.add_directive('ipython', IPythonDirective) - app.add_config_value('ipython_savefig_dir', 'savefig', 'env') - app.add_config_value('ipython_warning_is_error', True, 'env') - app.add_config_value('ipython_rgxin', - re.compile(r'In \[(\d+)\]:\s?(.*)\s*'), 'env') - app.add_config_value('ipython_rgxout', - re.compile(r'Out\[(\d+)\]:\s?(.*)\s*'), 'env') - app.add_config_value('ipython_promptin', 'In [%d]:', 'env') - app.add_config_value('ipython_promptout', 'Out[%d]:', 'env') - - # We could just let matplotlib pick whatever is specified as the default - # backend in the matplotlibrc file, but this would cause issues if the - # backend didn't work in headless environments. For this reason, 'agg' - # is a good default backend choice. - app.add_config_value('ipython_mplbackend', 'agg', 'env') - - # If the user sets this config value to `None`, then EmbeddedSphinxShell's - # __init__ method will treat it as []. - execlines = ['import numpy as np'] - if use_matplotlib: - execlines.append('import matplotlib.pyplot as plt') - app.add_config_value('ipython_execlines', execlines, 'env') - - app.add_config_value('ipython_holdcount', True, 'env') - - metadata = {'parallel_read_safe': True, 'parallel_write_safe': True} - return metadata - -# Simple smoke test, needs to be converted to a proper automatic test. -def test(): - - examples = [ - r""" -In [9]: pwd -Out[9]: '/home/jdhunter/py4science/book' - -In [10]: cd bookdata/ -/home/jdhunter/py4science/book/bookdata - -In [2]: from pylab import * - -In [2]: ion() - -In [3]: im = imread('stinkbug.png') - -@savefig mystinkbug.png width=4in -In [4]: imshow(im) -Out[4]: <matplotlib.image.AxesImage object at 0x39ea850> - -""", - r""" - -In [1]: x = 'hello world' - -# string methods can be -# used to alter the string -@doctest -In [2]: x.upper() -Out[2]: 'HELLO WORLD' - -@verbatim -In [3]: x.st<TAB> -x.startswith x.strip -""", - r""" - -In [130]: url = 'http://ichart.finance.yahoo.com/table.csv?s=CROX\ - .....: &d=9&e=22&f=2009&g=d&a=1&br=8&c=2006&ignore=.csv' - -In [131]: print url.split('&') -['http://ichart.finance.yahoo.com/table.csv?s=CROX', 'd=9', 'e=22', 'f=2009', 'g=d', 'a=1', 'b=8', 'c=2006', 'ignore=.csv'] - -In [60]: import urllib - -""", - r"""\ - -In [133]: import numpy.random - -@suppress -In [134]: numpy.random.seed(2358) - -@doctest -In [135]: numpy.random.rand(10,2) -Out[135]: -array([[ 0.64524308, 0.59943846], - [ 0.47102322, 0.8715456 ], - [ 0.29370834, 0.74776844], - [ 0.99539577, 0.1313423 ], - [ 0.16250302, 0.21103583], - [ 0.81626524, 0.1312433 ], - [ 0.67338089, 0.72302393], - [ 0.7566368 , 0.07033696], - [ 0.22591016, 0.77731835], - [ 0.0072729 , 0.34273127]]) - -""", - - r""" -In [106]: print x -jdh - -In [109]: for i in range(10): - .....: print i - .....: - .....: -0 -1 -2 -3 -4 -5 -6 -7 -8 -9 -""", - - r""" - -In [144]: from pylab import * - -In [145]: ion() - -# use a semicolon to suppress the output -@savefig test_hist.png width=4in -In [151]: hist(np.random.randn(10000), 100); - - -@savefig test_plot.png width=4in -In [151]: plot(np.random.randn(10000), 'o'); - """, - - r""" -# use a semicolon to suppress the output -In [151]: plt.clf() - -@savefig plot_simple.png width=4in -In [151]: plot([1,2,3]) - -@savefig hist_simple.png width=4in -In [151]: hist(np.random.randn(10000), 100); - -""", - r""" -# update the current fig -In [151]: ylabel('number') - -In [152]: title('normal distribution') - - -@savefig hist_with_text.png -In [153]: grid(True) - -@doctest float -In [154]: 0.1 + 0.2 -Out[154]: 0.3 - -@doctest float -In [155]: np.arange(16).reshape(4,4) -Out[155]: -array([[ 0, 1, 2, 3], - [ 4, 5, 6, 7], - [ 8, 9, 10, 11], - [12, 13, 14, 15]]) - -In [1]: x = np.arange(16, dtype=float).reshape(4,4) - -In [2]: x[0,0] = np.inf - -In [3]: x[0,1] = np.nan - -@doctest float -In [4]: x -Out[4]: -array([[ inf, nan, 2., 3.], - [ 4., 5., 6., 7.], - [ 8., 9., 10., 11.], - [ 12., 13., 14., 15.]]) - - - """, - ] - # skip local-file depending first example: - examples = examples[1:] - - #ipython_directive.DEBUG = True # dbg - #options = dict(suppress=True) # dbg - options = {} - for example in examples: - content = example.split('\n') - IPythonDirective('debug', arguments=None, options=options, - content=content, lineno=0, - content_offset=None, block_text=None, - state=None, state_machine=None, - ) - -# Run test suite as a script -if __name__=='__main__': - if not os.path.isdir('_static'): - os.mkdir('_static') - test() - print('All OK? Check figures in _static/') diff --git a/contrib/python/ipython/py3/IPython/terminal/__init__.py b/contrib/python/ipython/py3/IPython/terminal/__init__.py deleted file mode 100644 index e69de29bb2..0000000000 --- a/contrib/python/ipython/py3/IPython/terminal/__init__.py +++ /dev/null diff --git a/contrib/python/ipython/py3/IPython/terminal/console.py b/contrib/python/ipython/py3/IPython/terminal/console.py deleted file mode 100644 index 65571a7572..0000000000 --- a/contrib/python/ipython/py3/IPython/terminal/console.py +++ /dev/null @@ -1,19 +0,0 @@ -""" -Shim to maintain backwards compatibility with old IPython.terminal.console imports. -""" -# Copyright (c) IPython Development Team. -# Distributed under the terms of the Modified BSD License. - -import sys -from warnings import warn - -from IPython.utils.shimmodule import ShimModule, ShimWarning - -warn("The `IPython.terminal.console` package has been deprecated since IPython 4.0. " - "You should import from jupyter_console instead.", ShimWarning) - -# Unconditionally insert the shim into sys.modules so that further import calls -# trigger the custom attribute access above - -sys.modules['IPython.terminal.console'] = ShimModule( - src='IPython.terminal.console', mirror='jupyter_console') diff --git a/contrib/python/ipython/py3/IPython/terminal/debugger.py b/contrib/python/ipython/py3/IPython/terminal/debugger.py deleted file mode 100644 index 8448d96370..0000000000 --- a/contrib/python/ipython/py3/IPython/terminal/debugger.py +++ /dev/null @@ -1,167 +0,0 @@ -import asyncio -import os -import sys - -from IPython.core.debugger import Pdb -from IPython.core.completer import IPCompleter -from .ptutils import IPythonPTCompleter -from .shortcuts import create_ipython_shortcuts -from . import embed - -from pathlib import Path -from pygments.token import Token -from prompt_toolkit.shortcuts.prompt import PromptSession -from prompt_toolkit.enums import EditingMode -from prompt_toolkit.formatted_text import PygmentsTokens -from prompt_toolkit.history import InMemoryHistory, FileHistory -from concurrent.futures import ThreadPoolExecutor - -from prompt_toolkit import __version__ as ptk_version -PTK3 = ptk_version.startswith('3.') - - -class TerminalPdb(Pdb): - """Standalone IPython debugger.""" - - def __init__(self, *args, pt_session_options=None, **kwargs): - Pdb.__init__(self, *args, **kwargs) - self._ptcomp = None - self.pt_init(pt_session_options) - self.thread_executor = ThreadPoolExecutor(1) - - def pt_init(self, pt_session_options=None): - """Initialize the prompt session and the prompt loop - and store them in self.pt_app and self.pt_loop. - - Additional keyword arguments for the PromptSession class - can be specified in pt_session_options. - """ - if pt_session_options is None: - pt_session_options = {} - - def get_prompt_tokens(): - return [(Token.Prompt, self.prompt)] - - if self._ptcomp is None: - compl = IPCompleter( - shell=self.shell, namespace={}, global_namespace={}, parent=self.shell - ) - # add a completer for all the do_ methods - methods_names = [m[3:] for m in dir(self) if m.startswith("do_")] - - def gen_comp(self, text): - return [m for m in methods_names if m.startswith(text)] - import types - newcomp = types.MethodType(gen_comp, compl) - compl.custom_matchers.insert(0, newcomp) - # end add completer. - - self._ptcomp = IPythonPTCompleter(compl) - - # setup history only when we start pdb - if self.shell.debugger_history is None: - if self.shell.debugger_history_file is not None: - - p = Path(self.shell.debugger_history_file).expanduser() - if not p.exists(): - p.touch() - self.debugger_history = FileHistory(os.path.expanduser(str(p))) - else: - self.debugger_history = InMemoryHistory() - else: - self.debugger_history = self.shell.debugger_history - - options = dict( - message=(lambda: PygmentsTokens(get_prompt_tokens())), - editing_mode=getattr(EditingMode, self.shell.editing_mode.upper()), - key_bindings=create_ipython_shortcuts(self.shell), - history=self.debugger_history, - completer=self._ptcomp, - enable_history_search=True, - mouse_support=self.shell.mouse_support, - complete_style=self.shell.pt_complete_style, - style=getattr(self.shell, "style", None), - color_depth=self.shell.color_depth, - ) - - if not PTK3: - options['inputhook'] = self.shell.inputhook - options.update(pt_session_options) - self.pt_loop = asyncio.new_event_loop() - self.pt_app = PromptSession(**options) - - def cmdloop(self, intro=None): - """Repeatedly issue a prompt, accept input, parse an initial prefix - off the received input, and dispatch to action methods, passing them - the remainder of the line as argument. - - override the same methods from cmd.Cmd to provide prompt toolkit replacement. - """ - if not self.use_rawinput: - raise ValueError('Sorry ipdb does not support use_rawinput=False') - - # In order to make sure that prompt, which uses asyncio doesn't - # interfere with applications in which it's used, we always run the - # prompt itself in a different thread (we can't start an event loop - # within an event loop). This new thread won't have any event loop - # running, and here we run our prompt-loop. - self.preloop() - - try: - if intro is not None: - self.intro = intro - if self.intro: - print(self.intro, file=self.stdout) - stop = None - while not stop: - if self.cmdqueue: - line = self.cmdqueue.pop(0) - else: - self._ptcomp.ipy_completer.namespace = self.curframe_locals - self._ptcomp.ipy_completer.global_namespace = self.curframe.f_globals - - # Run the prompt in a different thread. - try: - line = self.thread_executor.submit(self.pt_app.prompt).result() - except EOFError: - line = "EOF" - - line = self.precmd(line) - stop = self.onecmd(line) - stop = self.postcmd(stop, line) - self.postloop() - except Exception: - raise - - def do_interact(self, arg): - ipshell = embed.InteractiveShellEmbed( - config=self.shell.config, - banner1="*interactive*", - exit_msg="*exiting interactive console...*", - ) - global_ns = self.curframe.f_globals - ipshell( - module=sys.modules.get(global_ns["__name__"], None), - local_ns=self.curframe_locals, - ) - - -def set_trace(frame=None): - """ - Start debugging from `frame`. - - If frame is not specified, debugging starts from caller's frame. - """ - TerminalPdb().set_trace(frame or sys._getframe().f_back) - - -if __name__ == '__main__': - import pdb - # IPython.core.debugger.Pdb.trace_dispatch shall not catch - # bdb.BdbQuit. When started through __main__ and an exception - # happened after hitting "c", this is needed in order to - # be able to quit the debugging session (see #9950). - old_trace_dispatch = pdb.Pdb.trace_dispatch - pdb.Pdb = TerminalPdb # type: ignore - pdb.Pdb.trace_dispatch = old_trace_dispatch # type: ignore - pdb.main() diff --git a/contrib/python/ipython/py3/IPython/terminal/embed.py b/contrib/python/ipython/py3/IPython/terminal/embed.py deleted file mode 100644 index 85e76d5558..0000000000 --- a/contrib/python/ipython/py3/IPython/terminal/embed.py +++ /dev/null @@ -1,410 +0,0 @@ -# encoding: utf-8 -""" -An embedded IPython shell. -""" -# Copyright (c) IPython Development Team. -# Distributed under the terms of the Modified BSD License. - - -import sys -import warnings - -from IPython.core import ultratb, compilerop -from IPython.core import magic_arguments -from IPython.core.magic import Magics, magics_class, line_magic -from IPython.core.interactiveshell import DummyMod, InteractiveShell -from IPython.terminal.interactiveshell import TerminalInteractiveShell -from IPython.terminal.ipapp import load_default_config - -from traitlets import Bool, CBool, Unicode -from IPython.utils.io import ask_yes_no - -from typing import Set - -class KillEmbedded(Exception):pass - -# kept for backward compatibility as IPython 6 was released with -# the typo. See https://github.com/ipython/ipython/pull/10706 -KillEmbeded = KillEmbedded - -# This is an additional magic that is exposed in embedded shells. -@magics_class -class EmbeddedMagics(Magics): - - @line_magic - @magic_arguments.magic_arguments() - @magic_arguments.argument('-i', '--instance', action='store_true', - help='Kill instance instead of call location') - @magic_arguments.argument('-x', '--exit', action='store_true', - help='Also exit the current session') - @magic_arguments.argument('-y', '--yes', action='store_true', - help='Do not ask confirmation') - def kill_embedded(self, parameter_s=''): - """%kill_embedded : deactivate for good the current embedded IPython - - This function (after asking for confirmation) sets an internal flag so - that an embedded IPython will never activate again for the given call - location. This is useful to permanently disable a shell that is being - called inside a loop: once you've figured out what you needed from it, - you may then kill it and the program will then continue to run without - the interactive shell interfering again. - - Kill Instance Option: - - If for some reasons you need to kill the location where the instance - is created and not called, for example if you create a single - instance in one place and debug in many locations, you can use the - ``--instance`` option to kill this specific instance. Like for the - ``call location`` killing an "instance" should work even if it is - recreated within a loop. - - .. note:: - - This was the default behavior before IPython 5.2 - - """ - - args = magic_arguments.parse_argstring(self.kill_embedded, parameter_s) - print(args) - if args.instance: - # let no ask - if not args.yes: - kill = ask_yes_no( - "Are you sure you want to kill this embedded instance? [y/N] ", 'n') - else: - kill = True - if kill: - self.shell._disable_init_location() - print("This embedded IPython instance will not reactivate anymore " - "once you exit.") - else: - if not args.yes: - kill = ask_yes_no( - "Are you sure you want to kill this embedded call_location? [y/N] ", 'n') - else: - kill = True - if kill: - self.shell.embedded_active = False - print("This embedded IPython call location will not reactivate anymore " - "once you exit.") - - if args.exit: - # Ask-exit does not really ask, it just set internals flags to exit - # on next loop. - self.shell.ask_exit() - - - @line_magic - def exit_raise(self, parameter_s=''): - """%exit_raise Make the current embedded kernel exit and raise and exception. - - This function sets an internal flag so that an embedded IPython will - raise a `IPython.terminal.embed.KillEmbedded` Exception on exit, and then exit the current I. This is - useful to permanently exit a loop that create IPython embed instance. - """ - - self.shell.should_raise = True - self.shell.ask_exit() - - -class _Sentinel: - def __init__(self, repr): - assert isinstance(repr, str) - self.repr = repr - - def __repr__(self): - return repr - - -class InteractiveShellEmbed(TerminalInteractiveShell): - - dummy_mode = Bool(False) - exit_msg = Unicode('') - embedded = CBool(True) - should_raise = CBool(False) - # Like the base class display_banner is not configurable, but here it - # is True by default. - display_banner = CBool(True) - exit_msg = Unicode() - - # When embedding, by default we don't change the terminal title - term_title = Bool(False, - help="Automatically set the terminal title" - ).tag(config=True) - - _inactive_locations: Set[str] = set() - - def _disable_init_location(self): - """Disable the current Instance creation location""" - InteractiveShellEmbed._inactive_locations.add(self._init_location_id) - - @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) - - @embedded_active.setter - def embedded_active(self, value): - if value: - InteractiveShellEmbed._inactive_locations.discard( - self._call_location_id) - InteractiveShellEmbed._inactive_locations.discard( - self._init_location_id) - else: - InteractiveShellEmbed._inactive_locations.add( - self._call_location_id) - - def __init__(self, **kw): - assert ( - "user_global_ns" not in kw - ), "Key word argument `user_global_ns` has been replaced by `user_module` since IPython 4.0." - - clid = kw.pop('_init_location_id', None) - if not clid: - frame = sys._getframe(1) - clid = '%s:%s' % (frame.f_code.co_filename, frame.f_lineno) - self._init_location_id = clid - - super(InteractiveShellEmbed,self).__init__(**kw) - - # don't use the ipython crash handler so that user exceptions aren't - # trapped - sys.excepthook = ultratb.FormattedTB(color_scheme=self.colors, - mode=self.xmode, - call_pdb=self.pdb) - - def init_sys_modules(self): - """ - Explicitly overwrite :mod:`IPython.core.interactiveshell` to do nothing. - """ - pass - - def init_magics(self): - super(InteractiveShellEmbed, self).init_magics() - self.register_magics(EmbeddedMagics) - - def __call__( - self, - header="", - local_ns=None, - module=None, - dummy=None, - stack_depth=1, - compile_flags=None, - **kw - ): - """Activate the interactive interpreter. - - __call__(self,header='',local_ns=None,module=None,dummy=None) -> Start - the interpreter shell with the given local and global namespaces, and - optionally print a header string at startup. - - The shell can be globally activated/deactivated using the - dummy_mode attribute. This allows you to turn off a shell used - for debugging globally. - - However, *each* time you call the shell you can override the current - state of dummy_mode with the optional keyword parameter 'dummy'. For - example, if you set dummy mode on with IPShell.dummy_mode = True, you - can still have a specific call work by making it as IPShell(dummy=False). - """ - - # we are called, set the underlying interactiveshell not to exit. - self.keep_running = True - - # If the user has turned it off, go away - clid = kw.pop('_call_location_id', None) - if not clid: - frame = sys._getframe(1) - clid = '%s:%s' % (frame.f_code.co_filename, frame.f_lineno) - self._call_location_id = clid - - if not self.embedded_active: - return - - # Normal exits from interactive mode set this flag, so the shell can't - # re-enter (it checks this variable at the start of interactive mode). - self.exit_now = False - - # Allow the dummy parameter to override the global __dummy_mode - if dummy or (dummy != 0 and self.dummy_mode): - return - - # self.banner is auto computed - if header: - self.old_banner2 = self.banner2 - self.banner2 = self.banner2 + '\n' + header + '\n' - else: - self.old_banner2 = '' - - if self.display_banner: - self.show_banner() - - # Call the embedding code with a stack depth of 1 so it can skip over - # our call and get the original caller's namespaces. - self.mainloop( - local_ns, module, stack_depth=stack_depth, compile_flags=compile_flags - ) - - self.banner2 = self.old_banner2 - - if self.exit_msg is not None: - print(self.exit_msg) - - if self.should_raise: - raise KillEmbedded('Embedded IPython raising error, as user requested.') - - def mainloop( - self, - local_ns=None, - module=None, - stack_depth=0, - compile_flags=None, - ): - """Embeds IPython into a running python program. - - Parameters - ---------- - local_ns, module - Working local namespace (a dict) and module (a module or similar - object). If given as None, they are automatically taken from the scope - where the shell was called, so that program variables become visible. - stack_depth : int - How many levels in the stack to go to looking for namespaces (when - local_ns or module is None). This allows an intermediate caller to - make sure that this function gets the namespace from the intended - level in the stack. By default (0) it will get its locals and globals - from the immediate caller. - compile_flags - A bit field identifying the __future__ features - that are enabled, as passed to the builtin :func:`compile` function. - If given as None, they are automatically taken from the scope where - the shell was called. - - """ - - # Get locals and globals from caller - if ((local_ns is None or module is None or compile_flags is None) - and self.default_user_namespaces): - call_frame = sys._getframe(stack_depth).f_back - - if local_ns is None: - local_ns = call_frame.f_locals - if module is None: - global_ns = call_frame.f_globals - try: - module = sys.modules[global_ns['__name__']] - except KeyError: - warnings.warn("Failed to get module %s" % \ - global_ns.get('__name__', 'unknown module') - ) - module = DummyMod() - module.__dict__ = global_ns - if compile_flags is None: - compile_flags = (call_frame.f_code.co_flags & - compilerop.PyCF_MASK) - - # Save original namespace and module so we can restore them after - # embedding; otherwise the shell doesn't shut down correctly. - orig_user_module = self.user_module - orig_user_ns = self.user_ns - orig_compile_flags = self.compile.flags - - # Update namespaces and fire up interpreter - - # The global one is easy, we can just throw it in - if module is not None: - self.user_module = module - - # But the user/local one is tricky: ipython needs it to store internal - # data, but we also need the locals. We'll throw our hidden variables - # like _ih and get_ipython() into the local namespace, but delete them - # later. - if local_ns is not None: - reentrant_local_ns = {k: v for (k, v) in local_ns.items() if k not in self.user_ns_hidden.keys()} - self.user_ns = reentrant_local_ns - self.init_user_ns() - - # Compiler flags - if compile_flags is not None: - self.compile.flags = compile_flags - - # make sure the tab-completer has the correct frame information, so it - # actually completes using the frame's locals/globals - self.set_completer_frame() - - with self.builtin_trap, self.display_trap: - self.interact() - - # now, purge out the local namespace of IPython's hidden variables. - if local_ns is not None: - local_ns.update({k: v for (k, v) in self.user_ns.items() if k not in self.user_ns_hidden.keys()}) - - - # Restore original namespace so shell can shut down when we exit. - self.user_module = orig_user_module - self.user_ns = orig_user_ns - self.compile.flags = orig_compile_flags - - -def embed(*, header="", compile_flags=None, **kwargs): - """Call this to embed IPython at the current point in your program. - - The first invocation of this will create an :class:`InteractiveShellEmbed` - instance and then call it. Consecutive calls just call the already - created instance. - - If you don't want the kernel to initialize the namespace - from the scope of the surrounding function, - and/or you want to load full IPython configuration, - you probably want `IPython.start_ipython()` instead. - - Here is a simple example:: - - from IPython import embed - a = 10 - b = 20 - embed(header='First time') - c = 30 - d = 40 - embed() - - Full customization can be done by passing a :class:`Config` in as the - config argument. - """ - config = kwargs.get('config') - if config is None: - config = load_default_config() - config.InteractiveShellEmbed = config.TerminalInteractiveShell - kwargs['config'] = config - using = kwargs.get('using', 'sync') - if using : - kwargs['config'].update({'TerminalInteractiveShell':{'loop_runner':using, 'colors':'NoColor', 'autoawait': using!='sync'}}) - #save ps1/ps2 if defined - ps1 = None - ps2 = None - try: - ps1 = sys.ps1 - ps2 = sys.ps2 - except AttributeError: - pass - #save previous instance - saved_shell_instance = InteractiveShell._instance - if saved_shell_instance is not None: - cls = type(saved_shell_instance) - cls.clear_instance() - frame = sys._getframe(1) - shell = InteractiveShellEmbed.instance(_init_location_id='%s:%s' % ( - frame.f_code.co_filename, frame.f_lineno), **kwargs) - shell(header=header, stack_depth=2, compile_flags=compile_flags, - _call_location_id='%s:%s' % (frame.f_code.co_filename, frame.f_lineno)) - InteractiveShellEmbed.clear_instance() - #restore previous instance - if saved_shell_instance is not None: - cls = type(saved_shell_instance) - cls.clear_instance() - for subclass in cls._walk_mro(): - subclass._instance = saved_shell_instance - if ps1 is not None: - sys.ps1 = ps1 - sys.ps2 = ps2 diff --git a/contrib/python/ipython/py3/IPython/terminal/interactiveshell.py b/contrib/python/ipython/py3/IPython/terminal/interactiveshell.py deleted file mode 100644 index 06724bea87..0000000000 --- a/contrib/python/ipython/py3/IPython/terminal/interactiveshell.py +++ /dev/null @@ -1,769 +0,0 @@ -"""IPython terminal interface using prompt_toolkit""" - -import asyncio -import os -import sys -from warnings import warn - -from IPython.core.async_helpers import get_asyncio_loop -from IPython.core.interactiveshell import InteractiveShell, InteractiveShellABC -from IPython.utils.py3compat import input -from IPython.utils.terminal import toggle_set_term_title, set_term_title, restore_term_title -from IPython.utils.process import abbrev_cwd -from traitlets import ( - Bool, - Unicode, - Dict, - Integer, - observe, - Instance, - Type, - default, - Enum, - Union, - Any, - validate, - Float, -) - -from prompt_toolkit.auto_suggest import AutoSuggestFromHistory -from prompt_toolkit.enums import DEFAULT_BUFFER, EditingMode -from prompt_toolkit.filters import (HasFocus, Condition, IsDone) -from prompt_toolkit.formatted_text import PygmentsTokens -from prompt_toolkit.history import History -from prompt_toolkit.layout.processors import ConditionalProcessor, HighlightMatchingBracketProcessor -from prompt_toolkit.output import ColorDepth -from prompt_toolkit.patch_stdout import patch_stdout -from prompt_toolkit.shortcuts import PromptSession, CompleteStyle, print_formatted_text -from prompt_toolkit.styles import DynamicStyle, merge_styles -from prompt_toolkit.styles.pygments import style_from_pygments_cls, style_from_pygments_dict -from prompt_toolkit import __version__ as ptk_version - -from pygments.styles import get_style_by_name -from pygments.style import Style -from pygments.token import Token - -from .debugger import TerminalPdb, Pdb -from .magics import TerminalMagics -from .pt_inputhooks import get_inputhook_name_and_func -from .prompts import Prompts, ClassicPrompts, RichPromptDisplayHook -from .ptutils import IPythonPTCompleter, IPythonPTLexer -from .shortcuts import create_ipython_shortcuts - -PTK3 = ptk_version.startswith('3.') - - -class _NoStyle(Style): pass - - - -_style_overrides_light_bg = { - Token.Prompt: '#ansibrightblue', - Token.PromptNum: '#ansiblue bold', - Token.OutPrompt: '#ansibrightred', - Token.OutPromptNum: '#ansired bold', -} - -_style_overrides_linux = { - Token.Prompt: '#ansibrightgreen', - Token.PromptNum: '#ansigreen bold', - Token.OutPrompt: '#ansibrightred', - Token.OutPromptNum: '#ansired bold', -} - -def get_default_editor(): - try: - return os.environ['EDITOR'] - except KeyError: - pass - except UnicodeError: - warn("$EDITOR environment variable is not pure ASCII. Using platform " - "default editor.") - - if os.name == 'posix': - return 'vi' # the only one guaranteed to be there! - else: - return 'notepad' # same in Windows! - -# conservatively check for tty -# overridden streams can result in things like: -# - sys.stdin = None -# - no isatty method -for _name in ('stdin', 'stdout', 'stderr'): - _stream = getattr(sys, _name) - if not _stream or not hasattr(_stream, 'isatty') or not _stream.isatty(): - _is_tty = False - break -else: - _is_tty = True - - -_use_simple_prompt = ('IPY_TEST_SIMPLE_PROMPT' in os.environ) or (not _is_tty) - -def black_reformat_handler(text_before_cursor): - """ - We do not need to protect against error, - this is taken care at a higher level where any reformat error is ignored. - Indeed we may call reformatting on incomplete code. - """ - import black - - formatted_text = black.format_str(text_before_cursor, mode=black.FileMode()) - if not text_before_cursor.endswith("\n") and formatted_text.endswith("\n"): - formatted_text = formatted_text[:-1] - return formatted_text - - -def yapf_reformat_handler(text_before_cursor): - from yapf.yapflib import file_resources - from yapf.yapflib import yapf_api - - style_config = file_resources.GetDefaultStyleForDir(os.getcwd()) - formatted_text, was_formatted = yapf_api.FormatCode( - text_before_cursor, style_config=style_config - ) - if was_formatted: - if not text_before_cursor.endswith("\n") and formatted_text.endswith("\n"): - formatted_text = formatted_text[:-1] - return formatted_text - else: - return text_before_cursor - - -class PtkHistoryAdapter(History): - """ - Prompt toolkit has it's own way of handling history, Where it assumes it can - Push/pull from history. - - """ - - def __init__(self, shell): - super().__init__() - self.shell = shell - self._refresh() - - def append_string(self, string): - # we rely on sql for that. - self._loaded = False - self._refresh() - - def _refresh(self): - if not self._loaded: - self._loaded_strings = list(self.load_history_strings()) - - def load_history_strings(self): - last_cell = "" - res = [] - for __, ___, cell in self.shell.history_manager.get_tail( - self.shell.history_load_length, include_latest=True - ): - # Ignore blank lines and consecutive duplicates - cell = cell.rstrip() - if cell and (cell != last_cell): - res.append(cell) - last_cell = cell - yield from res[::-1] - - def store_string(self, string: str) -> None: - pass - -class TerminalInteractiveShell(InteractiveShell): - mime_renderers = Dict().tag(config=True) - - space_for_menu = Integer(6, help='Number of line at the bottom of the screen ' - 'to reserve for the tab completion menu, ' - 'search history, ...etc, the height of ' - 'these menus will at most this value. ' - 'Increase it is you prefer long and skinny ' - 'menus, decrease for short and wide.' - ).tag(config=True) - - pt_app = None - debugger_history = None - - debugger_history_file = Unicode( - "~/.pdbhistory", help="File in which to store and read history" - ).tag(config=True) - - simple_prompt = Bool(_use_simple_prompt, - help="""Use `raw_input` for the REPL, without completion and prompt colors. - - Useful when controlling IPython as a subprocess, and piping STDIN/OUT/ERR. Known usage are: - IPython own testing machinery, and emacs inferior-shell integration through elpy. - - This mode default to `True` if the `IPY_TEST_SIMPLE_PROMPT` - environment variable is set, or the current terminal is not a tty.""" - ).tag(config=True) - - @property - def debugger_cls(self): - return Pdb if self.simple_prompt else TerminalPdb - - confirm_exit = Bool(True, - help=""" - Set to confirm when you try to exit IPython with an EOF (Control-D - in Unix, Control-Z/Enter in Windows). By typing 'exit' or 'quit', - you can force a direct exit without any confirmation.""", - ).tag(config=True) - - editing_mode = Unicode('emacs', - help="Shortcut style to use at the prompt. 'vi' or 'emacs'.", - ).tag(config=True) - - emacs_bindings_in_vi_insert_mode = Bool( - True, - help="Add shortcuts from 'emacs' insert mode to 'vi' insert mode.", - ).tag(config=True) - - modal_cursor = Bool( - True, - help=""" - Cursor shape changes depending on vi mode: beam in vi insert mode, - block in nav mode, underscore in replace mode.""", - ).tag(config=True) - - ttimeoutlen = Float( - 0.01, - help="""The time in milliseconds that is waited for a key code - to complete.""", - ).tag(config=True) - - timeoutlen = Float( - 0.5, - help="""The time in milliseconds that is waited for a mapped key - sequence to complete.""", - ).tag(config=True) - - autoformatter = Unicode( - None, - help="Autoformatter to reformat Terminal code. Can be `'black'`, `'yapf'` or `None`", - allow_none=True - ).tag(config=True) - - auto_match = Bool( - False, - help=""" - Automatically add/delete closing bracket or quote when opening bracket or quote is entered/deleted. - Brackets: (), [], {} - Quotes: '', \"\" - """, - ).tag(config=True) - - mouse_support = Bool(False, - help="Enable mouse support in the prompt\n(Note: prevents selecting text with the mouse)" - ).tag(config=True) - - # We don't load the list of styles for the help string, because loading - # Pygments plugins takes time and can cause unexpected errors. - highlighting_style = Union([Unicode('legacy'), Type(klass=Style)], - help="""The name or class of a Pygments style to use for syntax - highlighting. To see available styles, run `pygmentize -L styles`.""" - ).tag(config=True) - - @validate('editing_mode') - def _validate_editing_mode(self, proposal): - if proposal['value'].lower() == 'vim': - proposal['value']= 'vi' - elif proposal['value'].lower() == 'default': - proposal['value']= 'emacs' - - if hasattr(EditingMode, proposal['value'].upper()): - return proposal['value'].lower() - - return self.editing_mode - - - @observe('editing_mode') - def _editing_mode(self, change): - if self.pt_app: - self.pt_app.editing_mode = getattr(EditingMode, change.new.upper()) - - def _set_formatter(self, formatter): - if formatter is None: - self.reformat_handler = lambda x:x - elif formatter == 'black': - self.reformat_handler = black_reformat_handler - elif formatter == "yapf": - self.reformat_handler = yapf_reformat_handler - else: - raise ValueError - - @observe("autoformatter") - def _autoformatter_changed(self, change): - formatter = change.new - self._set_formatter(formatter) - - @observe('highlighting_style') - @observe('colors') - def _highlighting_style_changed(self, change): - self.refresh_style() - - def refresh_style(self): - self._style = self._make_style_from_name_or_cls(self.highlighting_style) - - - highlighting_style_overrides = Dict( - help="Override highlighting format for specific tokens" - ).tag(config=True) - - true_color = Bool(False, - help="""Use 24bit colors instead of 256 colors in prompt highlighting. - If your terminal supports true color, the following command should - print ``TRUECOLOR`` in orange:: - - printf \"\\x1b[38;2;255;100;0mTRUECOLOR\\x1b[0m\\n\" - """, - ).tag(config=True) - - editor = Unicode(get_default_editor(), - help="Set the editor used by IPython (default to $EDITOR/vi/notepad)." - ).tag(config=True) - - prompts_class = Type(Prompts, help='Class used to generate Prompt token for prompt_toolkit').tag(config=True) - - prompts = Instance(Prompts) - - @default('prompts') - def _prompts_default(self): - return self.prompts_class(self) - -# @observe('prompts') -# def _(self, change): -# self._update_layout() - - @default('displayhook_class') - def _displayhook_class_default(self): - return RichPromptDisplayHook - - term_title = Bool(True, - help="Automatically set the terminal title" - ).tag(config=True) - - term_title_format = Unicode("IPython: {cwd}", - help="Customize the terminal title format. This is a python format string. " + - "Available substitutions are: {cwd}." - ).tag(config=True) - - display_completions = Enum(('column', 'multicolumn','readlinelike'), - help= ( "Options for displaying tab completions, 'column', 'multicolumn', and " - "'readlinelike'. These options are for `prompt_toolkit`, see " - "`prompt_toolkit` documentation for more information." - ), - default_value='multicolumn').tag(config=True) - - highlight_matching_brackets = Bool(True, - help="Highlight matching brackets.", - ).tag(config=True) - - extra_open_editor_shortcuts = Bool(False, - help="Enable vi (v) or Emacs (C-X C-E) shortcuts to open an external editor. " - "This is in addition to the F2 binding, which is always enabled." - ).tag(config=True) - - handle_return = Any(None, - help="Provide an alternative handler to be called when the user presses " - "Return. This is an advanced option intended for debugging, which " - "may be changed or removed in later releases." - ).tag(config=True) - - enable_history_search = Bool(True, - help="Allows to enable/disable the prompt toolkit history search" - ).tag(config=True) - - autosuggestions_provider = Unicode( - "AutoSuggestFromHistory", - help="Specifies from which source automatic suggestions are provided. " - "Can be set to `'AutoSuggestFromHistory`' or `None` to disable" - "automatic suggestions. Default is `'AutoSuggestFromHistory`'.", - allow_none=True, - ).tag(config=True) - - def _set_autosuggestions(self, provider): - if provider is None: - self.auto_suggest = None - elif provider == "AutoSuggestFromHistory": - self.auto_suggest = AutoSuggestFromHistory() - else: - raise ValueError("No valid provider.") - if self.pt_app: - self.pt_app.auto_suggest = self.auto_suggest - - @observe("autosuggestions_provider") - def _autosuggestions_provider_changed(self, change): - provider = change.new - self._set_autosuggestions(provider) - - prompt_includes_vi_mode = Bool(True, - help="Display the current vi mode (when using vi editing mode)." - ).tag(config=True) - - @observe('term_title') - def init_term_title(self, change=None): - # Enable or disable the terminal title. - if self.term_title: - toggle_set_term_title(True) - set_term_title(self.term_title_format.format(cwd=abbrev_cwd())) - else: - toggle_set_term_title(False) - - def restore_term_title(self): - if self.term_title: - restore_term_title() - - def init_display_formatter(self): - super(TerminalInteractiveShell, self).init_display_formatter() - # terminal only supports plain text - self.display_formatter.active_types = ["text/plain"] - - def init_prompt_toolkit_cli(self): - if self.simple_prompt: - # Fall back to plain non-interactive output for tests. - # This is very limited. - def prompt(): - prompt_text = "".join(x[1] for x in self.prompts.in_prompt_tokens()) - lines = [input(prompt_text)] - prompt_continuation = "".join(x[1] for x in self.prompts.continuation_prompt_tokens()) - while self.check_complete('\n'.join(lines))[0] == 'incomplete': - lines.append( input(prompt_continuation) ) - return '\n'.join(lines) - self.prompt_for_code = prompt - return - - # Set up keyboard shortcuts - key_bindings = create_ipython_shortcuts(self) - - - # Pre-populate history from IPython's history database - history = PtkHistoryAdapter(self) - - self._style = self._make_style_from_name_or_cls(self.highlighting_style) - self.style = DynamicStyle(lambda: self._style) - - editing_mode = getattr(EditingMode, self.editing_mode.upper()) - - self.pt_loop = asyncio.new_event_loop() - self.pt_app = PromptSession( - auto_suggest=self.auto_suggest, - editing_mode=editing_mode, - key_bindings=key_bindings, - history=history, - completer=IPythonPTCompleter(shell=self), - enable_history_search=self.enable_history_search, - style=self.style, - include_default_pygments_style=False, - mouse_support=self.mouse_support, - enable_open_in_editor=self.extra_open_editor_shortcuts, - color_depth=self.color_depth, - tempfile_suffix=".py", - **self._extra_prompt_options() - ) - - def _make_style_from_name_or_cls(self, name_or_cls): - """ - Small wrapper that make an IPython compatible style from a style name - - We need that to add style for prompt ... etc. - """ - style_overrides = {} - if name_or_cls == 'legacy': - legacy = self.colors.lower() - if legacy == 'linux': - style_cls = get_style_by_name('monokai') - style_overrides = _style_overrides_linux - elif legacy == 'lightbg': - style_overrides = _style_overrides_light_bg - style_cls = get_style_by_name('pastie') - elif legacy == 'neutral': - # The default theme needs to be visible on both a dark background - # and a light background, because we can't tell what the terminal - # looks like. These tweaks to the default theme help with that. - style_cls = get_style_by_name('default') - style_overrides.update({ - Token.Number: '#ansigreen', - Token.Operator: 'noinherit', - Token.String: '#ansiyellow', - Token.Name.Function: '#ansiblue', - Token.Name.Class: 'bold #ansiblue', - Token.Name.Namespace: 'bold #ansiblue', - Token.Name.Variable.Magic: '#ansiblue', - Token.Prompt: '#ansigreen', - Token.PromptNum: '#ansibrightgreen bold', - Token.OutPrompt: '#ansired', - Token.OutPromptNum: '#ansibrightred bold', - }) - - # Hack: Due to limited color support on the Windows console - # the prompt colors will be wrong without this - if os.name == 'nt': - style_overrides.update({ - Token.Prompt: '#ansidarkgreen', - Token.PromptNum: '#ansigreen bold', - Token.OutPrompt: '#ansidarkred', - Token.OutPromptNum: '#ansired bold', - }) - elif legacy =='nocolor': - style_cls=_NoStyle - style_overrides = {} - else : - raise ValueError('Got unknown colors: ', legacy) - else : - if isinstance(name_or_cls, str): - style_cls = get_style_by_name(name_or_cls) - else: - style_cls = name_or_cls - style_overrides = { - Token.Prompt: '#ansigreen', - Token.PromptNum: '#ansibrightgreen bold', - Token.OutPrompt: '#ansired', - Token.OutPromptNum: '#ansibrightred bold', - } - style_overrides.update(self.highlighting_style_overrides) - style = merge_styles([ - style_from_pygments_cls(style_cls), - style_from_pygments_dict(style_overrides), - ]) - - return style - - @property - def pt_complete_style(self): - return { - 'multicolumn': CompleteStyle.MULTI_COLUMN, - 'column': CompleteStyle.COLUMN, - 'readlinelike': CompleteStyle.READLINE_LIKE, - }[self.display_completions] - - @property - def color_depth(self): - return (ColorDepth.TRUE_COLOR if self.true_color else None) - - def _extra_prompt_options(self): - """ - Return the current layout option for the current Terminal InteractiveShell - """ - def get_message(): - return PygmentsTokens(self.prompts.in_prompt_tokens()) - - if self.editing_mode == 'emacs': - # with emacs mode the prompt is (usually) static, so we call only - # the function once. With VI mode it can toggle between [ins] and - # [nor] so we can't precompute. - # here I'm going to favor the default keybinding which almost - # everybody uses to decrease CPU usage. - # if we have issues with users with custom Prompts we can see how to - # work around this. - get_message = get_message() - - options = { - 'complete_in_thread': False, - 'lexer':IPythonPTLexer(), - 'reserve_space_for_menu':self.space_for_menu, - 'message': get_message, - 'prompt_continuation': ( - lambda width, lineno, is_soft_wrap: - PygmentsTokens(self.prompts.continuation_prompt_tokens(width))), - 'multiline': True, - 'complete_style': self.pt_complete_style, - - # Highlight matching brackets, but only when this setting is - # enabled, and only when the DEFAULT_BUFFER has the focus. - 'input_processors': [ConditionalProcessor( - processor=HighlightMatchingBracketProcessor(chars='[](){}'), - filter=HasFocus(DEFAULT_BUFFER) & ~IsDone() & - Condition(lambda: self.highlight_matching_brackets))], - } - if not PTK3: - options['inputhook'] = self.inputhook - - return options - - def prompt_for_code(self): - if self.rl_next_input: - default = self.rl_next_input - self.rl_next_input = None - else: - default = '' - - # In order to make sure that asyncio code written in the - # interactive shell doesn't interfere with the prompt, we run the - # prompt in a different event loop. - # If we don't do this, people could spawn coroutine with a - # while/true inside which will freeze the prompt. - - policy = asyncio.get_event_loop_policy() - old_loop = get_asyncio_loop() - - # FIXME: prompt_toolkit is using the deprecated `asyncio.get_event_loop` - # to get the current event loop. - # This will probably be replaced by an attribute or input argument, - # at which point we can stop calling the soon-to-be-deprecated `set_event_loop` here. - if old_loop is not self.pt_loop: - policy.set_event_loop(self.pt_loop) - try: - with patch_stdout(raw=True): - text = self.pt_app.prompt( - default=default, - **self._extra_prompt_options()) - finally: - # Restore the original event loop. - if old_loop is not None and old_loop is not self.pt_loop: - policy.set_event_loop(old_loop) - - return text - - def enable_win_unicode_console(self): - # Since IPython 7.10 doesn't support python < 3.6 and PEP 528, Python uses the unicode APIs for the Windows - # console by default, so WUC shouldn't be needed. - warn("`enable_win_unicode_console` is deprecated since IPython 7.10, does not do anything and will be removed in the future", - DeprecationWarning, - stacklevel=2) - - def init_io(self): - if sys.platform not in {'win32', 'cli'}: - return - - import colorama - colorama.init() - - def init_magics(self): - super(TerminalInteractiveShell, self).init_magics() - self.register_magics(TerminalMagics) - - def init_alias(self): - # The parent class defines aliases that can be safely used with any - # frontend. - super(TerminalInteractiveShell, self).init_alias() - - # Now define aliases that only make sense on the terminal, because they - # need direct access to the console in a way that we can't emulate in - # GUI or web frontend - if os.name == 'posix': - for cmd in ('clear', 'more', 'less', 'man'): - self.alias_manager.soft_define_alias(cmd, cmd) - - - def __init__(self, *args, **kwargs): - super(TerminalInteractiveShell, self).__init__(*args, **kwargs) - self._set_autosuggestions(self.autosuggestions_provider) - self.init_prompt_toolkit_cli() - self.init_term_title() - self.keep_running = True - self._set_formatter(self.autoformatter) - - - def ask_exit(self): - self.keep_running = False - - rl_next_input = None - - def interact(self): - self.keep_running = True - while self.keep_running: - print(self.separate_in, end='') - - try: - code = self.prompt_for_code() - except EOFError: - if (not self.confirm_exit) \ - or self.ask_yes_no('Do you really want to exit ([y]/n)?','y','n'): - self.ask_exit() - - else: - if code: - self.run_cell(code, store_history=True) - - def mainloop(self): - # An extra layer of protection in case someone mashing Ctrl-C breaks - # out of our internal code. - while True: - try: - self.interact() - break - except KeyboardInterrupt as e: - print("\n%s escaped interact()\n" % type(e).__name__) - finally: - # An interrupt during the eventloop will mess up the - # internal state of the prompt_toolkit library. - # Stopping the eventloop fixes this, see - # https://github.com/ipython/ipython/pull/9867 - if hasattr(self, '_eventloop'): - self._eventloop.stop() - - self.restore_term_title() - - # try to call some at-exit operation optimistically as some things can't - # be done during interpreter shutdown. this is technically inaccurate as - # this make mainlool not re-callable, but that should be a rare if not - # in existent use case. - - self._atexit_once() - - - _inputhook = None - def inputhook(self, context): - if self._inputhook is not None: - self._inputhook(context) - - active_eventloop = None - def enable_gui(self, gui=None): - if gui and (gui != 'inline') : - self.active_eventloop, self._inputhook =\ - get_inputhook_name_and_func(gui) - else: - self.active_eventloop = self._inputhook = None - - # For prompt_toolkit 3.0. We have to create an asyncio event loop with - # this inputhook. - if PTK3: - import asyncio - from prompt_toolkit.eventloop import new_eventloop_with_inputhook - - if gui == 'asyncio': - # When we integrate the asyncio event loop, run the UI in the - # same event loop as the rest of the code. don't use an actual - # input hook. (Asyncio is not made for nesting event loops.) - self.pt_loop = get_asyncio_loop() - - elif self._inputhook: - # If an inputhook was set, create a new asyncio event loop with - # this inputhook for the prompt. - self.pt_loop = new_eventloop_with_inputhook(self._inputhook) - else: - # When there's no inputhook, run the prompt in a separate - # asyncio event loop. - self.pt_loop = asyncio.new_event_loop() - - # Run !system commands directly, not through pipes, so terminal programs - # work correctly. - system = InteractiveShell.system_raw - - def auto_rewrite_input(self, cmd): - """Overridden from the parent class to use fancy rewriting prompt""" - if not self.show_rewritten_input: - return - - tokens = self.prompts.rewrite_prompt_tokens() - if self.pt_app: - print_formatted_text(PygmentsTokens(tokens), end='', - style=self.pt_app.app.style) - print(cmd) - else: - prompt = ''.join(s for t, s in tokens) - print(prompt, cmd, sep='') - - _prompts_before = None - def switch_doctest_mode(self, mode): - """Switch prompts to classic for %doctest_mode""" - if mode: - self._prompts_before = self.prompts - self.prompts = ClassicPrompts(self) - elif self._prompts_before: - self.prompts = self._prompts_before - self._prompts_before = None -# self._update_layout() - - -InteractiveShellABC.register(TerminalInteractiveShell) - -if __name__ == '__main__': - TerminalInteractiveShell.instance().interact() diff --git a/contrib/python/ipython/py3/IPython/terminal/ipapp.py b/contrib/python/ipython/py3/IPython/terminal/ipapp.py deleted file mode 100644 index a87eb2f443..0000000000 --- a/contrib/python/ipython/py3/IPython/terminal/ipapp.py +++ /dev/null @@ -1,342 +0,0 @@ -#!/usr/bin/env python -# encoding: utf-8 -""" -The :class:`~traitlets.config.application.Application` object for the command -line :command:`ipython` program. -""" - -# Copyright (c) IPython Development Team. -# Distributed under the terms of the Modified BSD License. - - -import logging -import os -import sys -import warnings - -from traitlets.config.loader import Config -from traitlets.config.application import boolean_flag, catch_config_error -from IPython.core import release -from IPython.core import usage -from IPython.core.completer import IPCompleter -from IPython.core.crashhandler import CrashHandler -from IPython.core.formatters import PlainTextFormatter -from IPython.core.history import HistoryManager -from IPython.core.application import ( - ProfileDir, BaseIPythonApplication, base_flags, base_aliases -) -from IPython.core.magic import MagicsManager -from IPython.core.magics import ( - ScriptMagics, LoggingMagics -) -from IPython.core.shellapp import ( - InteractiveShellApp, shell_flags, shell_aliases -) -from IPython.extensions.storemagic import StoreMagics -from .interactiveshell import TerminalInteractiveShell -from IPython.paths import get_ipython_dir -from traitlets import ( - Bool, List, default, observe, Type -) - -#----------------------------------------------------------------------------- -# Globals, utilities and helpers -#----------------------------------------------------------------------------- - -_examples = """ -ipython --matplotlib # enable matplotlib integration -ipython --matplotlib=qt # enable matplotlib integration with qt4 backend - -ipython --log-level=DEBUG # set logging to DEBUG -ipython --profile=foo # start with profile foo - -ipython profile create foo # create profile foo w/ default config files -ipython help profile # show the help for the profile subcmd - -ipython locate # print the path to the IPython directory -ipython locate profile foo # print the path to the directory for profile `foo` -""" - -#----------------------------------------------------------------------------- -# Crash handler for this application -#----------------------------------------------------------------------------- - -class IPAppCrashHandler(CrashHandler): - """sys.excepthook for IPython itself, leaves a detailed report on disk.""" - - def __init__(self, app): - contact_name = release.author - contact_email = release.author_email - bug_tracker = 'https://github.com/ipython/ipython/issues' - super(IPAppCrashHandler,self).__init__( - app, contact_name, contact_email, bug_tracker - ) - - def make_report(self,traceback): - """Return a string containing a crash report.""" - - sec_sep = self.section_sep - # Start with parent report - report = [super(IPAppCrashHandler, self).make_report(traceback)] - # Add interactive-specific info we may have - rpt_add = report.append - try: - rpt_add(sec_sep+"History of session input:") - for line in self.app.shell.user_ns['_ih']: - rpt_add(line) - rpt_add('\n*** Last line of input (may not be in above history):\n') - rpt_add(self.app.shell._last_input_line+'\n') - except: - pass - - return ''.join(report) - -#----------------------------------------------------------------------------- -# Aliases and Flags -#----------------------------------------------------------------------------- -flags = dict(base_flags) -flags.update(shell_flags) -frontend_flags = {} -addflag = lambda *args: frontend_flags.update(boolean_flag(*args)) -addflag('autoedit-syntax', 'TerminalInteractiveShell.autoedit_syntax', - 'Turn on auto editing of files with syntax errors.', - 'Turn off auto editing of files with syntax errors.' -) -addflag('simple-prompt', 'TerminalInteractiveShell.simple_prompt', - "Force simple minimal prompt using `raw_input`", - "Use a rich interactive prompt with prompt_toolkit", -) - -addflag('banner', 'TerminalIPythonApp.display_banner', - "Display a banner upon starting IPython.", - "Don't display a banner upon starting IPython." -) -addflag('confirm-exit', 'TerminalInteractiveShell.confirm_exit', - """Set to confirm when you try to exit IPython with an EOF (Control-D - in Unix, Control-Z/Enter in Windows). By typing 'exit' or 'quit', - you can force a direct exit without any confirmation.""", - "Don't prompt the user when exiting." -) -addflag('term-title', 'TerminalInteractiveShell.term_title', - "Enable auto setting the terminal title.", - "Disable auto setting the terminal title." -) -classic_config = Config() -classic_config.InteractiveShell.cache_size = 0 -classic_config.PlainTextFormatter.pprint = False -classic_config.TerminalInteractiveShell.prompts_class='IPython.terminal.prompts.ClassicPrompts' -classic_config.InteractiveShell.separate_in = '' -classic_config.InteractiveShell.separate_out = '' -classic_config.InteractiveShell.separate_out2 = '' -classic_config.InteractiveShell.colors = 'NoColor' -classic_config.InteractiveShell.xmode = 'Plain' - -frontend_flags['classic']=( - classic_config, - "Gives IPython a similar feel to the classic Python prompt." -) -# # log doesn't make so much sense this way anymore -# paa('--log','-l', -# action='store_true', dest='InteractiveShell.logstart', -# help="Start logging to the default log file (./ipython_log.py).") -# -# # quick is harder to implement -frontend_flags['quick']=( - {'TerminalIPythonApp' : {'quick' : True}}, - "Enable quick startup with no config files." -) - -frontend_flags['i'] = ( - {'TerminalIPythonApp' : {'force_interact' : True}}, - """If running code from the command line, become interactive afterwards. - It is often useful to follow this with `--` to treat remaining flags as - script arguments. - """ -) -flags.update(frontend_flags) - -aliases = dict(base_aliases) -aliases.update(shell_aliases) - -#----------------------------------------------------------------------------- -# Main classes and functions -#----------------------------------------------------------------------------- - - -class LocateIPythonApp(BaseIPythonApplication): - description = """print the path to the IPython dir""" - subcommands = dict( - profile=('IPython.core.profileapp.ProfileLocate', - "print the path to an IPython profile directory", - ), - ) - def start(self): - if self.subapp is not None: - return self.subapp.start() - else: - print(self.ipython_dir) - - -class TerminalIPythonApp(BaseIPythonApplication, InteractiveShellApp): - name = u'ipython' - description = usage.cl_usage - crash_handler_class = IPAppCrashHandler - examples = _examples - - flags = flags - aliases = aliases - classes = List() - - interactive_shell_class = Type( - klass=object, # use default_value otherwise which only allow subclasses. - default_value=TerminalInteractiveShell, - help="Class to use to instantiate the TerminalInteractiveShell object. Useful for custom Frontends" - ).tag(config=True) - - @default('classes') - def _classes_default(self): - """This has to be in a method, for TerminalIPythonApp to be available.""" - return [ - InteractiveShellApp, # ShellApp comes before TerminalApp, because - self.__class__, # it will also affect subclasses (e.g. QtConsole) - TerminalInteractiveShell, - HistoryManager, - MagicsManager, - ProfileDir, - PlainTextFormatter, - IPCompleter, - ScriptMagics, - LoggingMagics, - StoreMagics, - ] - - subcommands = dict( - profile = ("IPython.core.profileapp.ProfileApp", - "Create and manage IPython profiles." - ), - kernel = ("ipykernel.kernelapp.IPKernelApp", - "Start a kernel without an attached frontend." - ), - locate=('IPython.terminal.ipapp.LocateIPythonApp', - LocateIPythonApp.description - ), - history=('IPython.core.historyapp.HistoryApp', - "Manage the IPython history database." - ), - ) - - - # *do* autocreate requested profile, but don't create the config file. - auto_create=Bool(True) - # configurables - quick = Bool(False, - help="""Start IPython quickly by skipping the loading of config files.""" - ).tag(config=True) - @observe('quick') - def _quick_changed(self, change): - if change['new']: - self.load_config_file = lambda *a, **kw: None - - display_banner = Bool(True, - help="Whether to display a banner upon starting IPython." - ).tag(config=True) - - # if there is code of files to run from the cmd line, don't interact - # unless the --i flag (App.force_interact) is true. - force_interact = Bool(False, - help="""If a command or file is given via the command-line, - e.g. 'ipython foo.py', start an interactive shell after executing the - file or command.""" - ).tag(config=True) - @observe('force_interact') - def _force_interact_changed(self, change): - if change['new']: - self.interact = True - - @observe('file_to_run', 'code_to_run', 'module_to_run') - def _file_to_run_changed(self, change): - new = change['new'] - if new: - self.something_to_run = True - if new and not self.force_interact: - self.interact = False - - # internal, not-configurable - something_to_run=Bool(False) - - @catch_config_error - def initialize(self, argv=None): - """Do actions after construct, but before starting the app.""" - super(TerminalIPythonApp, self).initialize(argv) - if self.subapp is not None: - # don't bother initializing further, starting subapp - return - # print self.extra_args - if self.extra_args and not self.something_to_run: - self.file_to_run = self.extra_args[0] - self.init_path() - # create the shell - self.init_shell() - # and draw the banner - self.init_banner() - # Now a variety of things that happen after the banner is printed. - self.init_gui_pylab() - self.init_extensions() - self.init_code() - - def init_shell(self): - """initialize the InteractiveShell instance""" - # Create an InteractiveShell instance. - # shell.display_banner should always be False for the terminal - # based app, because we call shell.show_banner() by hand below - # so the banner shows *before* all extension loading stuff. - self.shell = self.interactive_shell_class.instance(parent=self, - profile_dir=self.profile_dir, - ipython_dir=self.ipython_dir, user_ns=self.user_ns) - self.shell.configurables.append(self) - - def init_banner(self): - """optionally display the banner""" - if self.display_banner and self.interact: - self.shell.show_banner() - # Make sure there is a space below the banner. - if self.log_level <= logging.INFO: print() - - def _pylab_changed(self, name, old, new): - """Replace --pylab='inline' with --pylab='auto'""" - if new == 'inline': - warnings.warn("'inline' not available as pylab backend, " - "using 'auto' instead.") - self.pylab = 'auto' - - def start(self): - if self.subapp is not None: - return self.subapp.start() - # perform any prexec steps: - if self.interact: - self.log.debug("Starting IPython's mainloop...") - self.shell.mainloop() - else: - self.log.debug("IPython not interactive...") - if not self.shell.last_execution_succeeded: - sys.exit(1) - -def load_default_config(ipython_dir=None): - """Load the default config file from the default ipython_dir. - - This is useful for embedded shells. - """ - if ipython_dir is None: - ipython_dir = get_ipython_dir() - - profile_dir = os.path.join(ipython_dir, 'profile_default') - app = TerminalIPythonApp() - app.config_file_paths.append(profile_dir) - app.load_config_file() - return app.config - -launch_new_instance = TerminalIPythonApp.launch_instance - - -if __name__ == '__main__': - launch_new_instance() diff --git a/contrib/python/ipython/py3/IPython/terminal/magics.py b/contrib/python/ipython/py3/IPython/terminal/magics.py deleted file mode 100644 index 206ff20a0f..0000000000 --- a/contrib/python/ipython/py3/IPython/terminal/magics.py +++ /dev/null @@ -1,214 +0,0 @@ -"""Extra magics for terminal use.""" - -# Copyright (c) IPython Development Team. -# Distributed under the terms of the Modified BSD License. - - -from logging import error -import os -import sys - -from IPython.core.error import TryNext, UsageError -from IPython.core.magic import Magics, magics_class, line_magic -from IPython.lib.clipboard import ClipboardEmpty -from IPython.testing.skipdoctest import skip_doctest -from IPython.utils.text import SList, strip_email_quotes -from IPython.utils import py3compat - -def get_pasted_lines(sentinel, l_input=py3compat.input, quiet=False): - """ Yield pasted lines until the user enters the given sentinel value. - """ - if not quiet: - print("Pasting code; enter '%s' alone on the line to stop or use Ctrl-D." \ - % sentinel) - prompt = ":" - else: - prompt = "" - while True: - try: - l = l_input(prompt) - if l == sentinel: - return - else: - yield l - except EOFError: - print('<EOF>') - return - - -@magics_class -class TerminalMagics(Magics): - def __init__(self, shell): - super(TerminalMagics, self).__init__(shell) - - def store_or_execute(self, block, name): - """ Execute a block, or store it in a variable, per the user's request. - """ - if name: - # If storing it for further editing - self.shell.user_ns[name] = SList(block.splitlines()) - print("Block assigned to '%s'" % name) - else: - b = self.preclean_input(block) - self.shell.user_ns['pasted_block'] = b - self.shell.using_paste_magics = True - try: - self.shell.run_cell(b, store_history=True) - finally: - self.shell.using_paste_magics = False - - def preclean_input(self, block): - lines = block.splitlines() - while lines and not lines[0].strip(): - lines = lines[1:] - return strip_email_quotes('\n'.join(lines)) - - def rerun_pasted(self, name='pasted_block'): - """ Rerun a previously pasted command. - """ - b = self.shell.user_ns.get(name) - - # Sanity checks - if b is None: - raise UsageError('No previous pasted block available') - if not isinstance(b, str): - raise UsageError( - "Variable 'pasted_block' is not a string, can't execute") - - print("Re-executing '%s...' (%d chars)"% (b.split('\n',1)[0], len(b))) - self.shell.run_cell(b) - - @line_magic - def autoindent(self, parameter_s = ''): - """Toggle autoindent on/off (deprecated)""" - self.shell.set_autoindent() - print("Automatic indentation is:",['OFF','ON'][self.shell.autoindent]) - - @skip_doctest - @line_magic - def cpaste(self, parameter_s=''): - """Paste & execute a pre-formatted code block from clipboard. - - You must terminate the block with '--' (two minus-signs) or Ctrl-D - alone on the line. You can also provide your own sentinel with '%paste - -s %%' ('%%' is the new sentinel for this operation). - - The block is dedented prior to execution to enable execution of method - definitions. '>' and '+' characters at the beginning of a line are - ignored, to allow pasting directly from e-mails, diff files and - doctests (the '...' continuation prompt is also stripped). The - executed block is also assigned to variable named 'pasted_block' for - later editing with '%edit pasted_block'. - - You can also pass a variable name as an argument, e.g. '%cpaste foo'. - This assigns the pasted block to variable 'foo' as string, without - dedenting or executing it (preceding >>> and + is still stripped) - - '%cpaste -r' re-executes the block previously entered by cpaste. - '%cpaste -q' suppresses any additional output messages. - - Do not be alarmed by garbled output on Windows (it's a readline bug). - Just press enter and type -- (and press enter again) and the block - will be what was just pasted. - - Shell escapes are not supported (yet). - - See Also - -------- - paste : automatically pull code from clipboard. - - Examples - -------- - :: - - In [8]: %cpaste - Pasting code; enter '--' alone on the line to stop. - :>>> a = ["world!", "Hello"] - :>>> print(" ".join(sorted(a))) - :-- - Hello world! - - :: - In [8]: %cpaste - Pasting code; enter '--' alone on the line to stop. - :>>> %alias_magic t timeit - :>>> %t -n1 pass - :-- - Created `%t` as an alias for `%timeit`. - Created `%%t` as an alias for `%%timeit`. - 354 ns ± 224 ns per loop (mean ± std. dev. of 7 runs, 1 loop each) - """ - opts, name = self.parse_options(parameter_s, 'rqs:', mode='string') - if 'r' in opts: - self.rerun_pasted() - return - - quiet = ('q' in opts) - - sentinel = opts.get('s', u'--') - block = '\n'.join(get_pasted_lines(sentinel, quiet=quiet)) - self.store_or_execute(block, name) - - @line_magic - def paste(self, parameter_s=''): - """Paste & execute a pre-formatted code block from clipboard. - - The text is pulled directly from the clipboard without user - intervention and printed back on the screen before execution (unless - the -q flag is given to force quiet mode). - - The block is dedented prior to execution to enable execution of method - definitions. '>' and '+' characters at the beginning of a line are - ignored, to allow pasting directly from e-mails, diff files and - doctests (the '...' continuation prompt is also stripped). The - executed block is also assigned to variable named 'pasted_block' for - later editing with '%edit pasted_block'. - - You can also pass a variable name as an argument, e.g. '%paste foo'. - This assigns the pasted block to variable 'foo' as string, without - executing it (preceding >>> and + is still stripped). - - Options: - - -r: re-executes the block previously entered by cpaste. - - -q: quiet mode: do not echo the pasted text back to the terminal. - - IPython statements (magics, shell escapes) are not supported (yet). - - See Also - -------- - cpaste : manually paste code into terminal until you mark its end. - """ - opts, name = self.parse_options(parameter_s, 'rq', mode='string') - if 'r' in opts: - self.rerun_pasted() - return - try: - block = self.shell.hooks.clipboard_get() - except TryNext as clipboard_exc: - message = getattr(clipboard_exc, 'args') - if message: - error(message[0]) - else: - error('Could not get text from the clipboard.') - return - except ClipboardEmpty as e: - raise UsageError("The clipboard appears to be empty") from e - - # By default, echo back to terminal unless quiet mode is requested - if 'q' not in opts: - sys.stdout.write(self.shell.pycolorize(block)) - if not block.endswith("\n"): - sys.stdout.write("\n") - sys.stdout.write("## -- End pasted text --\n") - - self.store_or_execute(block, name) - - # Class-level: add a '%cls' magic only on Windows - if sys.platform == 'win32': - @line_magic - def cls(self, s): - """Clear screen. - """ - os.system("cls") diff --git a/contrib/python/ipython/py3/IPython/terminal/prompts.py b/contrib/python/ipython/py3/IPython/terminal/prompts.py deleted file mode 100644 index 3f5c07b980..0000000000 --- a/contrib/python/ipython/py3/IPython/terminal/prompts.py +++ /dev/null @@ -1,108 +0,0 @@ -"""Terminal input and output prompts.""" - -from pygments.token import Token -import sys - -from IPython.core.displayhook import DisplayHook - -from prompt_toolkit.formatted_text import fragment_list_width, PygmentsTokens -from prompt_toolkit.shortcuts import print_formatted_text -from prompt_toolkit.enums import EditingMode - - -class Prompts(object): - def __init__(self, shell): - self.shell = shell - - def vi_mode(self): - if (getattr(self.shell.pt_app, 'editing_mode', None) == EditingMode.VI - and self.shell.prompt_includes_vi_mode): - mode = str(self.shell.pt_app.app.vi_state.input_mode) - if mode.startswith('InputMode.'): - mode = mode[10:13].lower() - elif mode.startswith('vi-'): - mode = mode[3:6] - return '['+mode+'] ' - return '' - - - def in_prompt_tokens(self): - return [ - (Token.Prompt, self.vi_mode() ), - (Token.Prompt, 'In ['), - (Token.PromptNum, str(self.shell.execution_count)), - (Token.Prompt, ']: '), - ] - - def _width(self): - return fragment_list_width(self.in_prompt_tokens()) - - def continuation_prompt_tokens(self, width=None): - if width is None: - width = self._width() - return [ - (Token.Prompt, (' ' * (width - 5)) + '...: '), - ] - - def rewrite_prompt_tokens(self): - width = self._width() - return [ - (Token.Prompt, ('-' * (width - 2)) + '> '), - ] - - def out_prompt_tokens(self): - return [ - (Token.OutPrompt, 'Out['), - (Token.OutPromptNum, str(self.shell.execution_count)), - (Token.OutPrompt, ']: '), - ] - -class ClassicPrompts(Prompts): - def in_prompt_tokens(self): - return [ - (Token.Prompt, '>>> '), - ] - - def continuation_prompt_tokens(self, width=None): - return [ - (Token.Prompt, '... ') - ] - - def rewrite_prompt_tokens(self): - return [] - - def out_prompt_tokens(self): - return [] - -class RichPromptDisplayHook(DisplayHook): - """Subclass of base display hook using coloured prompt""" - def write_output_prompt(self): - sys.stdout.write(self.shell.separate_out) - # If we're not displaying a prompt, it effectively ends with a newline, - # because the output will be left-aligned. - self.prompt_end_newline = True - - if self.do_full_cache: - tokens = self.shell.prompts.out_prompt_tokens() - prompt_txt = ''.join(s for t, s in tokens) - if prompt_txt and not prompt_txt.endswith('\n'): - # Ask for a newline before multiline output - self.prompt_end_newline = False - - if self.shell.pt_app: - print_formatted_text(PygmentsTokens(tokens), - style=self.shell.pt_app.app.style, end='', - ) - else: - sys.stdout.write(prompt_txt) - - def write_format_data(self, format_dict, md_dict=None) -> None: - if self.shell.mime_renderers: - - for mime, handler in self.shell.mime_renderers.items(): - if mime in format_dict: - handler(format_dict[mime], None) - return - - super().write_format_data(format_dict, md_dict) - diff --git a/contrib/python/ipython/py3/IPython/terminal/pt_inputhooks/__init__.py b/contrib/python/ipython/py3/IPython/terminal/pt_inputhooks/__init__.py deleted file mode 100644 index 69ff0ba1e6..0000000000 --- a/contrib/python/ipython/py3/IPython/terminal/pt_inputhooks/__init__.py +++ /dev/null @@ -1,62 +0,0 @@ -import importlib -import os - -aliases = { - 'qt4': 'qt', - 'gtk2': 'gtk', -} - -backends = [ - "qt", - "qt4", - "qt5", - "qt6", - "gtk", - "gtk2", - "gtk3", - "gtk4", - "tk", - "wx", - "pyglet", - "glut", - "osx", - "asyncio", -] - -registered = {} - -def register(name, inputhook): - """Register the function *inputhook* as an event loop integration.""" - registered[name] = inputhook - - -class UnknownBackend(KeyError): - def __init__(self, name): - self.name = name - - def __str__(self): - return ("No event loop integration for {!r}. " - "Supported event loops are: {}").format(self.name, - ', '.join(backends + sorted(registered))) - - -def get_inputhook_name_and_func(gui): - if gui in registered: - return gui, registered[gui] - - if gui not in backends: - raise UnknownBackend(gui) - - if gui in aliases: - return get_inputhook_name_and_func(aliases[gui]) - - gui_mod = gui - if gui == "qt5": - os.environ["QT_API"] = "pyqt5" - gui_mod = "qt" - elif gui == "qt6": - os.environ["QT_API"] = "pyqt6" - gui_mod = "qt" - - mod = importlib.import_module('IPython.terminal.pt_inputhooks.'+gui_mod) - return gui, mod.inputhook diff --git a/contrib/python/ipython/py3/IPython/terminal/pt_inputhooks/asyncio.py b/contrib/python/ipython/py3/IPython/terminal/pt_inputhooks/asyncio.py deleted file mode 100644 index 2d8c128208..0000000000 --- a/contrib/python/ipython/py3/IPython/terminal/pt_inputhooks/asyncio.py +++ /dev/null @@ -1,63 +0,0 @@ -""" -Inputhook for running the original asyncio event loop while we're waiting for -input. - -By default, in IPython, we run the prompt with a different asyncio event loop, -because otherwise we risk that people are freezing the prompt by scheduling bad -coroutines. E.g., a coroutine that does a while/true and never yield back -control to the loop. We can't cancel that. - -However, sometimes we want the asyncio loop to keep running while waiting for -a prompt. - -The following example will print the numbers from 1 to 10 above the prompt, -while we are waiting for input. (This works also because we use -prompt_toolkit`s `patch_stdout`):: - - In [1]: import asyncio - - In [2]: %gui asyncio - - In [3]: async def f(): - ...: for i in range(10): - ...: await asyncio.sleep(1) - ...: print(i) - - - In [4]: asyncio.ensure_future(f()) - -""" -from prompt_toolkit import __version__ as ptk_version - -from IPython.core.async_helpers import get_asyncio_loop - -PTK3 = ptk_version.startswith('3.') - - - -def inputhook(context): - """ - Inputhook for asyncio event loop integration. - """ - # For prompt_toolkit 3.0, this input hook literally doesn't do anything. - # The event loop integration here is implemented in `interactiveshell.py` - # by running the prompt itself in the current asyncio loop. The main reason - # for this is that nesting asyncio event loops is unreliable. - if PTK3: - return - - # For prompt_toolkit 2.0, we can run the current asyncio event loop, - # because prompt_toolkit 2.0 uses a different event loop internally. - - # get the persistent asyncio event loop - loop = get_asyncio_loop() - - def stop(): - loop.stop() - - fileno = context.fileno() - loop.add_reader(fileno, stop) - try: - loop.run_forever() - finally: - loop.remove_reader(fileno) diff --git a/contrib/python/ipython/py3/IPython/terminal/pt_inputhooks/glut.py b/contrib/python/ipython/py3/IPython/terminal/pt_inputhooks/glut.py deleted file mode 100644 index 835aadfc97..0000000000 --- a/contrib/python/ipython/py3/IPython/terminal/pt_inputhooks/glut.py +++ /dev/null @@ -1,140 +0,0 @@ -"""GLUT Input hook for interactive use with prompt_toolkit -""" - - -# GLUT is quite an old library and it is difficult to ensure proper -# integration within IPython since original GLUT does not allow to handle -# events one by one. Instead, it requires for the mainloop to be entered -# and never returned (there is not even a function to exit he -# mainloop). Fortunately, there are alternatives such as freeglut -# (available for linux and windows) and the OSX implementation gives -# access to a glutCheckLoop() function that blocks itself until a new -# event is received. This means we have to setup the idle callback to -# ensure we got at least one event that will unblock the function. -# -# Furthermore, it is not possible to install these handlers without a window -# being first created. We choose to make this window invisible. This means that -# display mode options are set at this level and user won't be able to change -# them later without modifying the code. This should probably be made available -# via IPython options system. - -import sys -import time -import signal -import OpenGL.GLUT as glut -import OpenGL.platform as platform -from timeit import default_timer as clock - -# Frame per second : 60 -# Should probably be an IPython option -glut_fps = 60 - -# Display mode : double buffeed + rgba + depth -# Should probably be an IPython option -glut_display_mode = (glut.GLUT_DOUBLE | - glut.GLUT_RGBA | - glut.GLUT_DEPTH) - -glutMainLoopEvent = None -if sys.platform == 'darwin': - try: - glutCheckLoop = platform.createBaseFunction( - 'glutCheckLoop', dll=platform.GLUT, resultType=None, - argTypes=[], - doc='glutCheckLoop( ) -> None', - argNames=(), - ) - except AttributeError as e: - raise RuntimeError( - '''Your glut implementation does not allow interactive sessions. ''' - '''Consider installing freeglut.''') from e - glutMainLoopEvent = glutCheckLoop -elif glut.HAVE_FREEGLUT: - glutMainLoopEvent = glut.glutMainLoopEvent -else: - raise RuntimeError( - '''Your glut implementation does not allow interactive sessions. ''' - '''Consider installing freeglut.''') - - -def glut_display(): - # Dummy display function - pass - -def glut_idle(): - # Dummy idle function - pass - -def glut_close(): - # Close function only hides the current window - glut.glutHideWindow() - glutMainLoopEvent() - -def glut_int_handler(signum, frame): - # Catch sigint and print the defaultipyt message - signal.signal(signal.SIGINT, signal.default_int_handler) - print('\nKeyboardInterrupt') - # Need to reprint the prompt at this stage - -# Initialisation code -glut.glutInit( sys.argv ) -glut.glutInitDisplayMode( glut_display_mode ) -# This is specific to freeglut -if bool(glut.glutSetOption): - glut.glutSetOption( glut.GLUT_ACTION_ON_WINDOW_CLOSE, - glut.GLUT_ACTION_GLUTMAINLOOP_RETURNS ) -glut.glutCreateWindow( b'ipython' ) -glut.glutReshapeWindow( 1, 1 ) -glut.glutHideWindow( ) -glut.glutWMCloseFunc( glut_close ) -glut.glutDisplayFunc( glut_display ) -glut.glutIdleFunc( glut_idle ) - - -def inputhook(context): - """Run the pyglet event loop by processing pending events only. - - This keeps processing pending events until stdin is ready. After - processing all pending events, a call to time.sleep is inserted. This is - needed, otherwise, CPU usage is at 100%. This sleep time should be tuned - though for best performance. - """ - # We need to protect against a user pressing Control-C when IPython is - # idle and this is running. We trap KeyboardInterrupt and pass. - - signal.signal(signal.SIGINT, glut_int_handler) - - try: - t = clock() - - # Make sure the default window is set after a window has been closed - if glut.glutGetWindow() == 0: - glut.glutSetWindow( 1 ) - glutMainLoopEvent() - return 0 - - while not context.input_is_ready(): - glutMainLoopEvent() - # We need to sleep at this point to keep the idle CPU load - # low. However, if sleep to long, GUI response is poor. As - # a compromise, we watch how often GUI events are being processed - # and switch between a short and long sleep time. Here are some - # stats useful in helping to tune this. - # time CPU load - # 0.001 13% - # 0.005 3% - # 0.01 1.5% - # 0.05 0.5% - used_time = clock() - t - if used_time > 10.0: - # print 'Sleep for 1 s' # dbg - time.sleep(1.0) - elif used_time > 0.1: - # Few GUI events coming in, so we can sleep longer - # print 'Sleep for 0.05 s' # dbg - time.sleep(0.05) - else: - # Many GUI events coming in, so sleep only very little - time.sleep(0.001) - except KeyboardInterrupt: - pass diff --git a/contrib/python/ipython/py3/IPython/terminal/pt_inputhooks/gtk.py b/contrib/python/ipython/py3/IPython/terminal/pt_inputhooks/gtk.py deleted file mode 100644 index 6e246ba837..0000000000 --- a/contrib/python/ipython/py3/IPython/terminal/pt_inputhooks/gtk.py +++ /dev/null @@ -1,58 +0,0 @@ -# Code borrowed from python-prompt-toolkit examples -# https://github.com/jonathanslenders/python-prompt-toolkit/blob/77cdcfbc7f4b4c34a9d2f9a34d422d7152f16209/examples/inputhook.py - -# Copyright (c) 2014, Jonathan Slenders -# All rights reserved. -# -# Redistribution and use in source and binary forms, with or without modification, -# are permitted provided that the following conditions are met: -# -# * Redistributions of source code must retain the above copyright notice, this -# list of conditions and the following disclaimer. -# -# * Redistributions in binary form must reproduce the above copyright notice, this -# list of conditions and the following disclaimer in the documentation and/or -# other materials provided with the distribution. -# -# * Neither the name of the {organization} nor the names of its -# contributors may be used to endorse or promote products derived from -# this software without specific prior written permission. -# -# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND -# ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED -# WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE -# DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR -# ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES -# (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; -# LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON -# ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS -# SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - -""" -PyGTK input hook for prompt_toolkit. - -Listens on the pipe prompt_toolkit sets up for a notification that it should -return control to the terminal event loop. -""" - -import gtk, gobject - -# Enable threading in GTK. (Otherwise, GTK will keep the GIL.) -gtk.gdk.threads_init() - -def inputhook(context): - """ - When the eventloop of prompt-toolkit is idle, call this inputhook. - - This will run the GTK main loop until the file descriptor - `context.fileno()` becomes ready. - - :param context: An `InputHookContext` instance. - """ - def _main_quit(*a, **kw): - gtk.main_quit() - return False - - gobject.io_add_watch(context.fileno(), gobject.IO_IN, _main_quit) - gtk.main() diff --git a/contrib/python/ipython/py3/IPython/terminal/pt_inputhooks/gtk3.py b/contrib/python/ipython/py3/IPython/terminal/pt_inputhooks/gtk3.py deleted file mode 100644 index ae82b4edaa..0000000000 --- a/contrib/python/ipython/py3/IPython/terminal/pt_inputhooks/gtk3.py +++ /dev/null @@ -1,12 +0,0 @@ -"""prompt_toolkit input hook for GTK 3 -""" - -from gi.repository import Gtk, GLib - -def _main_quit(*args, **kwargs): - Gtk.main_quit() - return False - -def inputhook(context): - GLib.io_add_watch(context.fileno(), GLib.PRIORITY_DEFAULT, GLib.IO_IN, _main_quit) - Gtk.main() diff --git a/contrib/python/ipython/py3/IPython/terminal/pt_inputhooks/gtk4.py b/contrib/python/ipython/py3/IPython/terminal/pt_inputhooks/gtk4.py deleted file mode 100644 index 009fbf1212..0000000000 --- a/contrib/python/ipython/py3/IPython/terminal/pt_inputhooks/gtk4.py +++ /dev/null @@ -1,27 +0,0 @@ -""" -prompt_toolkit input hook for GTK 4. -""" - -from gi.repository import GLib - - -class _InputHook: - def __init__(self, context): - self._quit = False - GLib.io_add_watch( - context.fileno(), GLib.PRIORITY_DEFAULT, GLib.IO_IN, self.quit - ) - - def quit(self, *args, **kwargs): - self._quit = True - return False - - def run(self): - context = GLib.MainContext.default() - while not self._quit: - context.iteration(True) - - -def inputhook(context): - hook = _InputHook(context) - hook.run() diff --git a/contrib/python/ipython/py3/IPython/terminal/pt_inputhooks/osx.py b/contrib/python/ipython/py3/IPython/terminal/pt_inputhooks/osx.py deleted file mode 100644 index 2754820efc..0000000000 --- a/contrib/python/ipython/py3/IPython/terminal/pt_inputhooks/osx.py +++ /dev/null @@ -1,157 +0,0 @@ -"""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")) # type: ignore - -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")) # type: ignore - -CFFileDescriptorCreate = CoreFoundation.CFFileDescriptorCreate -CFFileDescriptorCreate.restype = void_p -CFFileDescriptorCreate.argtypes = [void_p, ctypes.c_int, ctypes.c_bool, void_p, void_p] - -CFFileDescriptorGetNativeDescriptor = CoreFoundation.CFFileDescriptorGetNativeDescriptor -CFFileDescriptorGetNativeDescriptor.restype = ctypes.c_int -CFFileDescriptorGetNativeDescriptor.argtypes = [void_p] - -CFFileDescriptorEnableCallBacks = CoreFoundation.CFFileDescriptorEnableCallBacks -CFFileDescriptorEnableCallBacks.restype = None -CFFileDescriptorEnableCallBacks.argtypes = [void_p, ctypes.c_ulong] - -CFFileDescriptorCreateRunLoopSource = CoreFoundation.CFFileDescriptorCreateRunLoopSource -CFFileDescriptorCreateRunLoopSource.restype = void_p -CFFileDescriptorCreateRunLoopSource.argtypes = [void_p, void_p, void_p] - -CFRunLoopGetCurrent = CoreFoundation.CFRunLoopGetCurrent -CFRunLoopGetCurrent.restype = void_p - -CFRunLoopAddSource = CoreFoundation.CFRunLoopAddSource -CFRunLoopAddSource.restype = None -CFRunLoopAddSource.argtypes = [void_p, void_p, void_p] - -CFRelease = CoreFoundation.CFRelease -CFRelease.restype = None -CFRelease.argtypes = [void_p] - -CFFileDescriptorInvalidate = CoreFoundation.CFFileDescriptorInvalidate -CFFileDescriptorInvalidate.restype = None -CFFileDescriptorInvalidate.argtypes = [void_p] - -# From CFFileDescriptor.h -kCFFileDescriptorReadCallBack = 1 -kCFRunLoopCommonModes = void_p.in_dll(CoreFoundation, 'kCFRunLoopCommonModes') - - -def _NSApp(): - """Return the global NSApplication instance (NSApp)""" - objc.objc_msgSend.argtypes = [void_p, void_p] - return msg(C('NSApplication'), n('sharedApplication')) - - -def _wake(NSApp): - """Wake the Application""" - objc.objc_msgSend.argtypes = [ - void_p, - void_p, - void_p, - void_p, - void_p, - void_p, - void_p, - void_p, - void_p, - void_p, - void_p, - ] - event = msg( - C("NSEvent"), - n( - "otherEventWithType:location:modifierFlags:" - "timestamp:windowNumber:context:subtype:data1:data2:" - ), - 15, # Type - 0, # location - 0, # flags - 0, # timestamp - 0, # window - None, # context - 0, # subtype - 0, # data1 - 0, # data2 - ) - objc.objc_msgSend.argtypes = [void_p, void_p, void_p, void_p] - msg(NSApp, n('postEvent:atStart:'), void_p(event), True) - - -_triggered = Event() - -def _input_callback(fdref, flags, info): - """Callback to fire when there's input to be read""" - _triggered.set() - CFFileDescriptorInvalidate(fdref) - CFRelease(fdref) - NSApp = _NSApp() - objc.objc_msgSend.argtypes = [void_p, void_p, void_p] - msg(NSApp, n('stop:'), NSApp) - _wake(NSApp) - -_c_callback_func_type = ctypes.CFUNCTYPE(None, void_p, void_p, void_p) -_c_input_callback = _c_callback_func_type(_input_callback) - - -def _stop_on_read(fd): - """Register callback to stop eventloop when there's data on fd""" - _triggered.clear() - fdref = CFFileDescriptorCreate(None, fd, False, _c_input_callback, None) - CFFileDescriptorEnableCallBacks(fdref, kCFFileDescriptorReadCallBack) - source = CFFileDescriptorCreateRunLoopSource(None, fdref, 0) - loop = CFRunLoopGetCurrent() - CFRunLoopAddSource(loop, source, kCFRunLoopCommonModes) - CFRelease(source) - - -def inputhook(context): - """Inputhook for Cocoa (NSApp)""" - NSApp = _NSApp() - _stop_on_read(context.fileno()) - objc.objc_msgSend.argtypes = [void_p, void_p] - msg(NSApp, n('run')) - if not _triggered.is_set(): - # app closed without firing callback, - # probably due to last window being closed. - # Run the loop manually in this case, - # since there may be events still to process (#9734) - CoreFoundation.CFRunLoopRun() diff --git a/contrib/python/ipython/py3/IPython/terminal/pt_inputhooks/pyglet.py b/contrib/python/ipython/py3/IPython/terminal/pt_inputhooks/pyglet.py deleted file mode 100644 index 49ec86d223..0000000000 --- a/contrib/python/ipython/py3/IPython/terminal/pt_inputhooks/pyglet.py +++ /dev/null @@ -1,66 +0,0 @@ -"""Enable pyglet to be used interactively with prompt_toolkit -""" - -import sys -import time -from timeit import default_timer as clock -import pyglet - -# On linux only, window.flip() has a bug that causes an AttributeError on -# window close. For details, see: -# http://groups.google.com/group/pyglet-users/browse_thread/thread/47c1aab9aa4a3d23/c22f9e819826799e?#c22f9e819826799e - -if sys.platform.startswith('linux'): - def flip(window): - try: - window.flip() - except AttributeError: - pass -else: - def flip(window): - window.flip() - - -def inputhook(context): - """Run the pyglet event loop by processing pending events only. - - This keeps processing pending events until stdin is ready. After - processing all pending events, a call to time.sleep is inserted. This is - needed, otherwise, CPU usage is at 100%. This sleep time should be tuned - though for best performance. - """ - # We need to protect against a user pressing Control-C when IPython is - # idle and this is running. We trap KeyboardInterrupt and pass. - try: - t = clock() - while not context.input_is_ready(): - pyglet.clock.tick() - for window in pyglet.app.windows: - window.switch_to() - window.dispatch_events() - window.dispatch_event('on_draw') - flip(window) - - # We need to sleep at this point to keep the idle CPU load - # low. However, if sleep to long, GUI response is poor. As - # a compromise, we watch how often GUI events are being processed - # and switch between a short and long sleep time. Here are some - # stats useful in helping to tune this. - # time CPU load - # 0.001 13% - # 0.005 3% - # 0.01 1.5% - # 0.05 0.5% - used_time = clock() - t - if used_time > 10.0: - # print 'Sleep for 1 s' # dbg - time.sleep(1.0) - elif used_time > 0.1: - # Few GUI events coming in, so we can sleep longer - # print 'Sleep for 0.05 s' # dbg - time.sleep(0.05) - else: - # Many GUI events coming in, so sleep only very little - time.sleep(0.001) - except KeyboardInterrupt: - pass diff --git a/contrib/python/ipython/py3/IPython/terminal/pt_inputhooks/qt.py b/contrib/python/ipython/py3/IPython/terminal/pt_inputhooks/qt.py deleted file mode 100644 index f1e710aff5..0000000000 --- a/contrib/python/ipython/py3/IPython/terminal/pt_inputhooks/qt.py +++ /dev/null @@ -1,85 +0,0 @@ -import sys -import os -from IPython.external.qt_for_kernel import QtCore, QtGui, enum_helper -from IPython import get_ipython - -# If we create a QApplication, keep a reference to it so that it doesn't get -# garbage collected. -_appref = None -_already_warned = False - - -def _exec(obj): - # exec on PyQt6, exec_ elsewhere. - obj.exec() if hasattr(obj, "exec") else obj.exec_() - - -def _reclaim_excepthook(): - shell = get_ipython() - if shell is not None: - sys.excepthook = shell.excepthook - - -def inputhook(context): - global _appref - app = QtCore.QCoreApplication.instance() - if not app: - if sys.platform == 'linux': - if not os.environ.get('DISPLAY') \ - and not os.environ.get('WAYLAND_DISPLAY'): - import warnings - global _already_warned - if not _already_warned: - _already_warned = True - warnings.warn( - 'The DISPLAY or WAYLAND_DISPLAY environment variable is ' - 'not set or empty and Qt5 requires this environment ' - 'variable. Deactivate Qt5 code.' - ) - return - try: - QtCore.QApplication.setAttribute(QtCore.Qt.AA_EnableHighDpiScaling) - except AttributeError: # Only for Qt>=5.6, <6. - pass - try: - QtCore.QApplication.setHighDpiScaleFactorRoundingPolicy( - QtCore.Qt.HighDpiScaleFactorRoundingPolicy.PassThrough - ) - except AttributeError: # Only for Qt>=5.14. - pass - _appref = app = QtGui.QApplication([" "]) - - # "reclaim" IPython sys.excepthook after event loop starts - # without this, it defaults back to BaseIPythonApplication.excepthook - # and exceptions in the Qt event loop are rendered without traceback - # formatting and look like "bug in IPython". - QtCore.QTimer.singleShot(0, _reclaim_excepthook) - - event_loop = QtCore.QEventLoop(app) - - if sys.platform == 'win32': - # The QSocketNotifier method doesn't appear to work on Windows. - # Use polling instead. - timer = QtCore.QTimer() - timer.timeout.connect(event_loop.quit) - while not context.input_is_ready(): - timer.start(50) # 50 ms - _exec(event_loop) - timer.stop() - else: - # On POSIX platforms, we can use a file descriptor to quit the event - # loop when there is input ready to read. - notifier = QtCore.QSocketNotifier( - context.fileno(), enum_helper("QtCore.QSocketNotifier.Type").Read - ) - try: - # connect the callback we care about before we turn it on - # lambda is necessary as PyQT inspect the function signature to know - # what arguments to pass to. See https://github.com/ipython/ipython/pull/12355 - notifier.activated.connect(lambda: event_loop.exit()) - notifier.setEnabled(True) - # only start the event loop we are not already flipped - if not context.input_is_ready(): - _exec(event_loop) - finally: - notifier.setEnabled(False) diff --git a/contrib/python/ipython/py3/IPython/terminal/pt_inputhooks/tk.py b/contrib/python/ipython/py3/IPython/terminal/pt_inputhooks/tk.py deleted file mode 100644 index 2715505f1f..0000000000 --- a/contrib/python/ipython/py3/IPython/terminal/pt_inputhooks/tk.py +++ /dev/null @@ -1,90 +0,0 @@ -# Code borrowed from ptpython -# https://github.com/jonathanslenders/ptpython/blob/86b71a89626114b18898a0af463978bdb32eeb70/ptpython/eventloop.py - -# Copyright (c) 2015, Jonathan Slenders -# All rights reserved. -# -# Redistribution and use in source and binary forms, with or without modification, -# are permitted provided that the following conditions are met: -# -# * Redistributions of source code must retain the above copyright notice, this -# list of conditions and the following disclaimer. -# -# * Redistributions in binary form must reproduce the above copyright notice, this -# list of conditions and the following disclaimer in the documentation and/or -# other materials provided with the distribution. -# -# * Neither the name of the {organization} nor the names of its -# contributors may be used to endorse or promote products derived from -# this software without specific prior written permission. -# -# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND -# ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED -# WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE -# DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR -# ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES -# (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; -# LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON -# ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS -# SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - -""" -Wrapper around the eventloop that gives some time to the Tkinter GUI to process -events when it's loaded and while we are waiting for input at the REPL. This -way we don't block the UI of for instance ``turtle`` and other Tk libraries. - -(Normally Tkinter registers it's callbacks in ``PyOS_InputHook`` to integrate -in readline. ``prompt-toolkit`` doesn't understand that input hook, but this -will fix it for Tk.) -""" -import time - -import _tkinter -import tkinter - -def inputhook(inputhook_context): - """ - Inputhook for Tk. - Run the Tk eventloop until prompt-toolkit needs to process the next input. - """ - # Get the current TK application. - root = tkinter._default_root - - def wait_using_filehandler(): - """ - Run the TK eventloop until the file handler that we got from the - inputhook becomes readable. - """ - # Add a handler that sets the stop flag when `prompt-toolkit` has input - # to process. - stop = [False] - def done(*a): - stop[0] = True - - root.createfilehandler(inputhook_context.fileno(), _tkinter.READABLE, done) - - # Run the TK event loop as long as we don't receive input. - while root.dooneevent(_tkinter.ALL_EVENTS): - if stop[0]: - break - - root.deletefilehandler(inputhook_context.fileno()) - - def wait_using_polling(): - """ - Windows TK doesn't support 'createfilehandler'. - So, run the TK eventloop and poll until input is ready. - """ - while not inputhook_context.input_is_ready(): - while root.dooneevent(_tkinter.ALL_EVENTS | _tkinter.DONT_WAIT): - pass - # Sleep to make the CPU idle, but not too long, so that the UI - # stays responsive. - time.sleep(.01) - - if root is not None: - if hasattr(root, 'createfilehandler'): - wait_using_filehandler() - else: - wait_using_polling() diff --git a/contrib/python/ipython/py3/IPython/terminal/pt_inputhooks/wx.py b/contrib/python/ipython/py3/IPython/terminal/pt_inputhooks/wx.py deleted file mode 100644 index a0f4442c77..0000000000 --- a/contrib/python/ipython/py3/IPython/terminal/pt_inputhooks/wx.py +++ /dev/null @@ -1,219 +0,0 @@ -"""Enable wxPython to be used interactively in prompt_toolkit -""" - -import sys -import signal -import time -from timeit import default_timer as clock -import wx - - -def ignore_keyboardinterrupts(func): - """Decorator which causes KeyboardInterrupt exceptions to be ignored during - execution of the decorated function. - - This is used by the inputhook functions to handle the event where the user - presses CTRL+C while IPython is idle, and the inputhook loop is running. In - this case, we want to ignore interrupts. - """ - def wrapper(*args, **kwargs): - try: - func(*args, **kwargs) - except KeyboardInterrupt: - pass - return wrapper - - -@ignore_keyboardinterrupts -def inputhook_wx1(context): - """Run the wx event loop by processing pending events only. - - This approach seems to work, but its performance is not great as it - relies on having PyOS_InputHook called regularly. - """ - app = wx.GetApp() - if app is not None: - assert wx.Thread_IsMain() - - # Make a temporary event loop and process system events until - # there are no more waiting, then allow idle events (which - # will also deal with pending or posted wx events.) - evtloop = wx.EventLoop() - ea = wx.EventLoopActivator(evtloop) - while evtloop.Pending(): - evtloop.Dispatch() - app.ProcessIdle() - del ea - return 0 - - -class EventLoopTimer(wx.Timer): - - def __init__(self, func): - self.func = func - wx.Timer.__init__(self) - - def Notify(self): - self.func() - - -class EventLoopRunner(object): - - def Run(self, time, input_is_ready): - self.input_is_ready = input_is_ready - self.evtloop = wx.EventLoop() - self.timer = EventLoopTimer(self.check_stdin) - self.timer.Start(time) - self.evtloop.Run() - - def check_stdin(self): - if self.input_is_ready(): - self.timer.Stop() - self.evtloop.Exit() - - -@ignore_keyboardinterrupts -def inputhook_wx2(context): - """Run the wx event loop, polling for stdin. - - This version runs the wx eventloop for an undetermined amount of time, - during which it periodically checks to see if anything is ready on - stdin. If anything is ready on stdin, the event loop exits. - - The argument to elr.Run controls how often the event loop looks at stdin. - This determines the responsiveness at the keyboard. A setting of 1000 - enables a user to type at most 1 char per second. I have found that a - setting of 10 gives good keyboard response. We can shorten it further, - but eventually performance would suffer from calling select/kbhit too - often. - """ - app = wx.GetApp() - if app is not None: - assert wx.Thread_IsMain() - elr = EventLoopRunner() - # As this time is made shorter, keyboard response improves, but idle - # CPU load goes up. 10 ms seems like a good compromise. - elr.Run(time=10, # CHANGE time here to control polling interval - input_is_ready=context.input_is_ready) - return 0 - - -@ignore_keyboardinterrupts -def inputhook_wx3(context): - """Run the wx event loop by processing pending events only. - - This is like inputhook_wx1, but it keeps processing pending events - until stdin is ready. After processing all pending events, a call to - time.sleep is inserted. This is needed, otherwise, CPU usage is at 100%. - This sleep time should be tuned though for best performance. - """ - app = wx.GetApp() - if app is not None: - assert wx.Thread_IsMain() - - # The import of wx on Linux sets the handler for signal.SIGINT - # to 0. This is a bug in wx or gtk. We fix by just setting it - # back to the Python default. - if not callable(signal.getsignal(signal.SIGINT)): - signal.signal(signal.SIGINT, signal.default_int_handler) - - evtloop = wx.EventLoop() - ea = wx.EventLoopActivator(evtloop) - t = clock() - while not context.input_is_ready(): - while evtloop.Pending(): - t = clock() - evtloop.Dispatch() - app.ProcessIdle() - # We need to sleep at this point to keep the idle CPU load - # low. However, if sleep to long, GUI response is poor. As - # a compromise, we watch how often GUI events are being processed - # and switch between a short and long sleep time. Here are some - # stats useful in helping to tune this. - # time CPU load - # 0.001 13% - # 0.005 3% - # 0.01 1.5% - # 0.05 0.5% - used_time = clock() - t - if used_time > 10.0: - # print 'Sleep for 1 s' # dbg - time.sleep(1.0) - elif used_time > 0.1: - # Few GUI events coming in, so we can sleep longer - # print 'Sleep for 0.05 s' # dbg - time.sleep(0.05) - else: - # Many GUI events coming in, so sleep only very little - time.sleep(0.001) - del ea - return 0 - - -@ignore_keyboardinterrupts -def inputhook_wxphoenix(context): - """Run the wx event loop until the user provides more input. - - This input hook is suitable for use with wxPython >= 4 (a.k.a. Phoenix). - - It uses the same approach to that used in - ipykernel.eventloops.loop_wx. The wx.MainLoop is executed, and a wx.Timer - is used to periodically poll the context for input. As soon as input is - ready, the wx.MainLoop is stopped. - """ - - app = wx.GetApp() - - if app is None: - return - - if context.input_is_ready(): - return - - assert wx.IsMainThread() - - # Wx uses milliseconds - poll_interval = 100 - - # Use a wx.Timer to periodically check whether input is ready - as soon as - # it is, we exit the main loop - timer = wx.Timer() - - def poll(ev): - if context.input_is_ready(): - timer.Stop() - app.ExitMainLoop() - - timer.Start(poll_interval) - timer.Bind(wx.EVT_TIMER, poll) - - # The import of wx on Linux sets the handler for signal.SIGINT to 0. This - # is a bug in wx or gtk. We fix by just setting it back to the Python - # default. - if not callable(signal.getsignal(signal.SIGINT)): - signal.signal(signal.SIGINT, signal.default_int_handler) - - # The SetExitOnFrameDelete call allows us to run the wx mainloop without - # having a frame open. - app.SetExitOnFrameDelete(False) - app.MainLoop() - - -# Get the major wx version number to figure out what input hook we should use. -major_version = 3 - -try: - major_version = int(wx.__version__[0]) -except Exception: - pass - -# Use the phoenix hook on all platforms for wxpython >= 4 -if major_version >= 4: - inputhook = inputhook_wxphoenix -# On OSX, evtloop.Pending() always returns True, regardless of there being -# any events pending. As such we can't use implementations 1 or 3 of the -# inputhook as those depend on a pending/dispatch loop. -elif sys.platform == 'darwin': - inputhook = inputhook_wx2 -else: - inputhook = inputhook_wx3 diff --git a/contrib/python/ipython/py3/IPython/terminal/ptutils.py b/contrib/python/ipython/py3/IPython/terminal/ptutils.py deleted file mode 100644 index c390d4972a..0000000000 --- a/contrib/python/ipython/py3/IPython/terminal/ptutils.py +++ /dev/null @@ -1,197 +0,0 @@ -"""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.core.completer import ( - provisionalcompleter, cursor_to_position, - _deduplicate_completions) -from prompt_toolkit.completion import Completer, Completion -from prompt_toolkit.lexers import Lexer -from prompt_toolkit.lexers import PygmentsLexer -from prompt_toolkit.patch_stdout import patch_stdout - -import pygments.lexers as pygments_lexers -import os -import sys -import traceback - -_completion_sentinel = object() - -def _elide_point(string:str, *, min_elide=30)->str: - """ - If a string is long enough, and has at least 3 dots, - replace the middle part with ellipses. - - If a string naming a file is long enough, and has at least 3 slashes, - replace the middle part with ellipses. - - If three consecutive dots, or two consecutive dots are encountered these are - replaced by the equivalents HORIZONTAL ELLIPSIS or TWO DOT LEADER unicode - equivalents - """ - string = string.replace('...','\N{HORIZONTAL ELLIPSIS}') - string = string.replace('..','\N{TWO DOT LEADER}') - if len(string) < min_elide: - return string - - object_parts = string.split('.') - file_parts = string.split(os.sep) - if file_parts[-1] == '': - file_parts.pop() - - if len(object_parts) > 3: - return '{}.{}\N{HORIZONTAL ELLIPSIS}{}.{}'.format(object_parts[0], object_parts[1][0], object_parts[-2][-1], object_parts[-1]) - - elif len(file_parts) > 3: - return ('{}' + os.sep + '{}\N{HORIZONTAL ELLIPSIS}{}' + os.sep + '{}').format(file_parts[0], file_parts[1][0], file_parts[-2][-1], file_parts[-1]) - - return string - -def _elide_typed(string:str, typed:str, *, min_elide:int=30)->str: - """ - Elide the middle of a long string if the beginning has already been typed. - """ - - if len(string) < min_elide: - return string - cut_how_much = len(typed)-3 - if cut_how_much < 7: - return string - if string.startswith(typed) and len(string)> len(typed): - return f"{string[:3]}\N{HORIZONTAL ELLIPSIS}{string[cut_how_much:]}" - return string - -def _elide(string:str, typed:str, min_elide=30)->str: - return _elide_typed( - _elide_point(string, min_elide=min_elide), - typed, min_elide=min_elide) - - - -def _adjust_completion_text_based_on_context(text, body, offset): - if text.endswith('=') and len(body) > offset and body[offset] == '=': - return text[:-1] - else: - return text - - -class IPythonPTCompleter(Completer): - """Adaptor to provide IPython completions to prompt_toolkit""" - def __init__(self, ipy_completer=None, shell=None): - if shell is None and ipy_completer is None: - raise TypeError("Please pass shell=an InteractiveShell instance.") - self._ipy_completer = ipy_completer - self.shell = shell - - @property - def ipy_completer(self): - if self._ipy_completer: - return self._ipy_completer - else: - return self.shell.Completer - - def get_completions(self, document, complete_event): - if not document.current_line.strip(): - return - # Some bits of our completion system may print stuff (e.g. if a module - # is imported). This context manager ensures that doesn't interfere with - # the prompt. - - with patch_stdout(), provisionalcompleter(): - body = document.text - cursor_row = document.cursor_position_row - cursor_col = document.cursor_position_col - cursor_position = document.cursor_position - offset = cursor_to_position(body, cursor_row, cursor_col) - try: - yield from self._get_completions(body, offset, cursor_position, self.ipy_completer) - except Exception as e: - try: - exc_type, exc_value, exc_tb = sys.exc_info() - traceback.print_exception(exc_type, exc_value, exc_tb) - except AttributeError: - print('Unrecoverable Error in completions') - - @staticmethod - def _get_completions(body, offset, cursor_position, ipyc): - """ - Private equivalent of get_completions() use only for unit_testing. - """ - debug = getattr(ipyc, 'debug', False) - completions = _deduplicate_completions( - body, ipyc.completions(body, offset)) - for c in completions: - if not c.text: - # Guard against completion machinery giving us an empty string. - continue - text = unicodedata.normalize('NFC', c.text) - # When the first character of the completion has a zero length, - # then it's probably a decomposed unicode character. E.g. caused by - # the "\dot" completion. Try to compose again with the previous - # character. - if wcwidth(text[0]) == 0: - if cursor_position + c.start > 0: - char_before = body[c.start - 1] - fixed_text = unicodedata.normalize( - 'NFC', char_before + text) - - # Yield the modified completion instead, if this worked. - if wcwidth(text[0:1]) == 1: - yield Completion(fixed_text, start_position=c.start - offset - 1) - continue - - # TODO: Use Jedi to determine meta_text - # (Jedi currently has a bug that results in incorrect information.) - # meta_text = '' - # yield Completion(m, start_position=start_pos, - # display_meta=meta_text) - display_text = c.text - - adjusted_text = _adjust_completion_text_based_on_context(c.text, body, offset) - if c.type == 'function': - yield Completion(adjusted_text, start_position=c.start - offset, display=_elide(display_text+'()', body[c.start:c.end]), display_meta=c.type+c.signature) - else: - yield Completion(adjusted_text, start_position=c.start - offset, display=_elide(display_text, body[c.start:c.end]), display_meta=c.type) - -class IPythonPTLexer(Lexer): - """ - Wrapper around PythonLexer and BashLexer. - """ - def __init__(self): - l = pygments_lexers - self.python_lexer = PygmentsLexer(l.Python3Lexer) - self.shell_lexer = PygmentsLexer(l.BashLexer) - - self.magic_lexers = { - 'HTML': PygmentsLexer(l.HtmlLexer), - 'html': PygmentsLexer(l.HtmlLexer), - 'javascript': PygmentsLexer(l.JavascriptLexer), - 'js': PygmentsLexer(l.JavascriptLexer), - 'perl': PygmentsLexer(l.PerlLexer), - 'ruby': PygmentsLexer(l.RubyLexer), - 'latex': PygmentsLexer(l.TexLexer), - } - - def lex_document(self, document): - text = document.text.lstrip() - - lexer = self.python_lexer - - if text.startswith('!') or text.startswith('%%bash'): - lexer = self.shell_lexer - - elif text.startswith('%%'): - for magic, l in self.magic_lexers.items(): - if text.startswith('%%' + magic): - lexer = l - break - - return lexer.lex_document(document) diff --git a/contrib/python/ipython/py3/IPython/terminal/shortcuts.py b/contrib/python/ipython/py3/IPython/terminal/shortcuts.py deleted file mode 100644 index 615397abc5..0000000000 --- a/contrib/python/ipython/py3/IPython/terminal/shortcuts.py +++ /dev/null @@ -1,544 +0,0 @@ -""" -Module to define and register Terminal IPython shortcuts with -:mod:`prompt_toolkit` -""" - -# Copyright (c) IPython Development Team. -# Distributed under the terms of the Modified BSD License. - -import warnings -import signal -import sys -import re -import os -from typing import Callable - - -from prompt_toolkit.application.current import get_app -from prompt_toolkit.enums import DEFAULT_BUFFER, SEARCH_BUFFER -from prompt_toolkit.filters import (has_focus, has_selection, Condition, - vi_insert_mode, emacs_insert_mode, has_completions, vi_mode) -from prompt_toolkit.key_binding.bindings.completion import display_completions_like_readline -from prompt_toolkit.key_binding import KeyBindings -from prompt_toolkit.key_binding.bindings import named_commands as nc -from prompt_toolkit.key_binding.vi_state import InputMode, ViState - -from IPython.utils.decorators import undoc - -@undoc -@Condition -def cursor_in_leading_ws(): - before = get_app().current_buffer.document.current_line_before_cursor - return (not before) or before.isspace() - - -def create_ipython_shortcuts(shell): - """Set up the prompt_toolkit keyboard shortcuts for IPython""" - - kb = KeyBindings() - insert_mode = vi_insert_mode | emacs_insert_mode - - if getattr(shell, 'handle_return', None): - return_handler = shell.handle_return(shell) - else: - return_handler = newline_or_execute_outer(shell) - - kb.add('enter', filter=(has_focus(DEFAULT_BUFFER) - & ~has_selection - & insert_mode - ))(return_handler) - - def reformat_and_execute(event): - reformat_text_before_cursor(event.current_buffer, event.current_buffer.document, shell) - event.current_buffer.validate_and_handle() - - kb.add('escape', 'enter', filter=(has_focus(DEFAULT_BUFFER) - & ~has_selection - & insert_mode - ))(reformat_and_execute) - - kb.add("c-\\")(quit) - - kb.add('c-p', filter=(vi_insert_mode & has_focus(DEFAULT_BUFFER)) - )(previous_history_or_previous_completion) - - kb.add('c-n', filter=(vi_insert_mode & has_focus(DEFAULT_BUFFER)) - )(next_history_or_next_completion) - - kb.add('c-g', filter=(has_focus(DEFAULT_BUFFER) & has_completions) - )(dismiss_completion) - - kb.add('c-c', filter=has_focus(DEFAULT_BUFFER))(reset_buffer) - - kb.add('c-c', filter=has_focus(SEARCH_BUFFER))(reset_search_buffer) - - supports_suspend = Condition(lambda: hasattr(signal, 'SIGTSTP')) - kb.add('c-z', filter=supports_suspend)(suspend_to_bg) - - # Ctrl+I == Tab - kb.add('tab', filter=(has_focus(DEFAULT_BUFFER) - & ~has_selection - & insert_mode - & cursor_in_leading_ws - ))(indent_buffer) - kb.add('c-o', filter=(has_focus(DEFAULT_BUFFER) & emacs_insert_mode) - )(newline_autoindent_outer(shell.input_transformer_manager)) - - kb.add('f2', filter=has_focus(DEFAULT_BUFFER))(open_input_in_editor) - - @Condition - def auto_match(): - return shell.auto_match - - focused_insert = (vi_insert_mode | emacs_insert_mode) & has_focus(DEFAULT_BUFFER) - _preceding_text_cache = {} - _following_text_cache = {} - - def preceding_text(pattern): - try: - return _preceding_text_cache[pattern] - except KeyError: - pass - m = re.compile(pattern) - - def _preceding_text(): - app = get_app() - return bool(m.match(app.current_buffer.document.current_line_before_cursor)) - - condition = Condition(_preceding_text) - _preceding_text_cache[pattern] = condition - return condition - - def following_text(pattern): - try: - return _following_text_cache[pattern] - except KeyError: - pass - m = re.compile(pattern) - - def _following_text(): - app = get_app() - return bool(m.match(app.current_buffer.document.current_line_after_cursor)) - - condition = Condition(_following_text) - _following_text_cache[pattern] = condition - return condition - - # auto match - @kb.add("(", filter=focused_insert & auto_match & following_text(r"[,)}\]]|$")) - def _(event): - event.current_buffer.insert_text("()") - event.current_buffer.cursor_left() - - @kb.add("[", filter=focused_insert & auto_match & following_text(r"[,)}\]]|$")) - def _(event): - event.current_buffer.insert_text("[]") - event.current_buffer.cursor_left() - - @kb.add("{", filter=focused_insert & auto_match & following_text(r"[,)}\]]|$")) - def _(event): - event.current_buffer.insert_text("{}") - event.current_buffer.cursor_left() - - @kb.add( - '"', - filter=focused_insert - & auto_match - & preceding_text(r'^([^"]+|"[^"]*")*$') - & following_text(r"[,)}\]]|$"), - ) - def _(event): - event.current_buffer.insert_text('""') - event.current_buffer.cursor_left() - - @kb.add( - "'", - filter=focused_insert - & auto_match - & preceding_text(r"^([^']+|'[^']*')*$") - & following_text(r"[,)}\]]|$"), - ) - def _(event): - event.current_buffer.insert_text("''") - event.current_buffer.cursor_left() - - # raw string - @kb.add( - "(", filter=focused_insert & auto_match & preceding_text(r".*(r|R)[\"'](-*)$") - ) - def _(event): - matches = re.match( - r".*(r|R)[\"'](-*)", - event.current_buffer.document.current_line_before_cursor, - ) - dashes = matches.group(2) or "" - event.current_buffer.insert_text("()" + dashes) - event.current_buffer.cursor_left(len(dashes) + 1) - - @kb.add( - "[", filter=focused_insert & auto_match & preceding_text(r".*(r|R)[\"'](-*)$") - ) - def _(event): - matches = re.match( - r".*(r|R)[\"'](-*)", - event.current_buffer.document.current_line_before_cursor, - ) - dashes = matches.group(2) or "" - event.current_buffer.insert_text("[]" + dashes) - event.current_buffer.cursor_left(len(dashes) + 1) - - @kb.add( - "{", filter=focused_insert & auto_match & preceding_text(r".*(r|R)[\"'](-*)$") - ) - def _(event): - matches = re.match( - r".*(r|R)[\"'](-*)", - event.current_buffer.document.current_line_before_cursor, - ) - dashes = matches.group(2) or "" - event.current_buffer.insert_text("{}" + dashes) - event.current_buffer.cursor_left(len(dashes) + 1) - - # just move cursor - @kb.add(")", filter=focused_insert & auto_match & following_text(r"^\)")) - @kb.add("]", filter=focused_insert & auto_match & following_text(r"^\]")) - @kb.add("}", filter=focused_insert & auto_match & following_text(r"^\}")) - @kb.add('"', filter=focused_insert & auto_match & following_text('^"')) - @kb.add("'", filter=focused_insert & auto_match & following_text("^'")) - def _(event): - event.current_buffer.cursor_right() - - @kb.add( - "backspace", - filter=focused_insert - & preceding_text(r".*\($") - & auto_match - & following_text(r"^\)"), - ) - @kb.add( - "backspace", - filter=focused_insert - & preceding_text(r".*\[$") - & auto_match - & following_text(r"^\]"), - ) - @kb.add( - "backspace", - filter=focused_insert - & preceding_text(r".*\{$") - & auto_match - & following_text(r"^\}"), - ) - @kb.add( - "backspace", - filter=focused_insert - & preceding_text('.*"$') - & auto_match - & following_text('^"'), - ) - @kb.add( - "backspace", - filter=focused_insert - & preceding_text(r".*'$") - & auto_match - & following_text(r"^'"), - ) - def _(event): - event.current_buffer.delete() - event.current_buffer.delete_before_cursor() - - if shell.display_completions == "readlinelike": - kb.add( - "c-i", - filter=( - has_focus(DEFAULT_BUFFER) - & ~has_selection - & insert_mode - & ~cursor_in_leading_ws - ), - )(display_completions_like_readline) - - if sys.platform == "win32": - kb.add("c-v", filter=(has_focus(DEFAULT_BUFFER) & ~vi_mode))(win_paste) - - @Condition - def ebivim(): - return shell.emacs_bindings_in_vi_insert_mode - - focused_insert_vi = has_focus(DEFAULT_BUFFER) & vi_insert_mode - - # Needed for to accept autosuggestions in vi insert mode - def _apply_autosuggest(event): - b = event.current_buffer - suggestion = b.suggestion - if suggestion is not None and suggestion.text: - b.insert_text(suggestion.text) - else: - nc.end_of_line(event) - - @kb.add("end", filter=has_focus(DEFAULT_BUFFER) & (ebivim | ~vi_insert_mode)) - def _(event): - _apply_autosuggest(event) - - @kb.add("c-e", filter=focused_insert_vi & ebivim) - def _(event): - _apply_autosuggest(event) - - @kb.add("c-f", filter=focused_insert_vi) - def _(event): - b = event.current_buffer - suggestion = b.suggestion - if suggestion: - b.insert_text(suggestion.text) - else: - nc.forward_char(event) - - @kb.add("escape", "f", filter=focused_insert_vi & ebivim) - def _(event): - b = event.current_buffer - suggestion = b.suggestion - if suggestion: - t = re.split(r"(\S+\s+)", suggestion.text) - b.insert_text(next((x for x in t if x), "")) - else: - nc.forward_word(event) - - # Simple Control keybindings - key_cmd_dict = { - "c-a": nc.beginning_of_line, - "c-b": nc.backward_char, - "c-k": nc.kill_line, - "c-w": nc.backward_kill_word, - "c-y": nc.yank, - "c-_": nc.undo, - } - - for key, cmd in key_cmd_dict.items(): - kb.add(key, filter=focused_insert_vi & ebivim)(cmd) - - # Alt and Combo Control keybindings - keys_cmd_dict = { - # Control Combos - ("c-x", "c-e"): nc.edit_and_execute, - ("c-x", "e"): nc.edit_and_execute, - # Alt - ("escape", "b"): nc.backward_word, - ("escape", "c"): nc.capitalize_word, - ("escape", "d"): nc.kill_word, - ("escape", "h"): nc.backward_kill_word, - ("escape", "l"): nc.downcase_word, - ("escape", "u"): nc.uppercase_word, - ("escape", "y"): nc.yank_pop, - ("escape", "."): nc.yank_last_arg, - } - - for keys, cmd in keys_cmd_dict.items(): - kb.add(*keys, filter=focused_insert_vi & ebivim)(cmd) - - def get_input_mode(self): - app = get_app() - app.ttimeoutlen = shell.ttimeoutlen - app.timeoutlen = shell.timeoutlen - - return self._input_mode - - def set_input_mode(self, mode): - shape = {InputMode.NAVIGATION: 2, InputMode.REPLACE: 4}.get(mode, 6) - cursor = "\x1b[{} q".format(shape) - - sys.stdout.write(cursor) - sys.stdout.flush() - - self._input_mode = mode - - if shell.editing_mode == "vi" and shell.modal_cursor: - ViState._input_mode = InputMode.INSERT - ViState.input_mode = property(get_input_mode, set_input_mode) - - return kb - - -def reformat_text_before_cursor(buffer, document, shell): - text = buffer.delete_before_cursor(len(document.text[:document.cursor_position])) - try: - formatted_text = shell.reformat_handler(text) - buffer.insert_text(formatted_text) - except Exception as e: - buffer.insert_text(text) - - -def newline_or_execute_outer(shell): - - def newline_or_execute(event): - """When the user presses return, insert a newline or execute the code.""" - b = event.current_buffer - d = b.document - - if b.complete_state: - cc = b.complete_state.current_completion - if cc: - b.apply_completion(cc) - else: - b.cancel_completion() - return - - # If there's only one line, treat it as if the cursor is at the end. - # See https://github.com/ipython/ipython/issues/10425 - if d.line_count == 1: - check_text = d.text - else: - check_text = d.text[:d.cursor_position] - status, indent = shell.check_complete(check_text) - - # if all we have after the cursor is whitespace: reformat current text - # before cursor - after_cursor = d.text[d.cursor_position:] - reformatted = False - if not after_cursor.strip(): - reformat_text_before_cursor(b, d, shell) - reformatted = True - if not (d.on_last_line or - d.cursor_position_row >= d.line_count - d.empty_line_count_at_the_end() - ): - if shell.autoindent: - b.insert_text('\n' + indent) - else: - b.insert_text('\n') - return - - if (status != 'incomplete') and b.accept_handler: - if not reformatted: - reformat_text_before_cursor(b, d, shell) - b.validate_and_handle() - else: - if shell.autoindent: - b.insert_text('\n' + indent) - else: - b.insert_text('\n') - return newline_or_execute - - -def previous_history_or_previous_completion(event): - """ - Control-P in vi edit mode on readline is history next, unlike default prompt toolkit. - - If completer is open this still select previous completion. - """ - event.current_buffer.auto_up() - - -def next_history_or_next_completion(event): - """ - Control-N in vi edit mode on readline is history previous, unlike default prompt toolkit. - - If completer is open this still select next completion. - """ - event.current_buffer.auto_down() - - -def dismiss_completion(event): - b = event.current_buffer - if b.complete_state: - b.cancel_completion() - - -def reset_buffer(event): - b = event.current_buffer - if b.complete_state: - b.cancel_completion() - else: - b.reset() - - -def reset_search_buffer(event): - if event.current_buffer.document.text: - event.current_buffer.reset() - else: - event.app.layout.focus(DEFAULT_BUFFER) - -def suspend_to_bg(event): - event.app.suspend_to_background() - -def quit(event): - """ - On platforms that support SIGQUIT, send SIGQUIT to the current process. - On other platforms, just exit the process with a message. - """ - sigquit = getattr(signal, "SIGQUIT", None) - if sigquit is not None: - os.kill(0, signal.SIGQUIT) - else: - sys.exit("Quit") - -def indent_buffer(event): - event.current_buffer.insert_text(' ' * 4) - -@undoc -def newline_with_copy_margin(event): - """ - DEPRECATED since IPython 6.0 - - See :any:`newline_autoindent_outer` for a replacement. - - Preserve margin and cursor position when using - Control-O to insert a newline in EMACS mode - """ - warnings.warn("`newline_with_copy_margin(event)` is deprecated since IPython 6.0. " - "see `newline_autoindent_outer(shell)(event)` for a replacement.", - DeprecationWarning, stacklevel=2) - - b = event.current_buffer - cursor_start_pos = b.document.cursor_position_col - b.newline(copy_margin=True) - b.cursor_up(count=1) - cursor_end_pos = b.document.cursor_position_col - if cursor_start_pos != cursor_end_pos: - pos_diff = cursor_start_pos - cursor_end_pos - b.cursor_right(count=pos_diff) - -def newline_autoindent_outer(inputsplitter) -> Callable[..., None]: - """ - Return a function suitable for inserting a indented newline after the cursor. - - Fancier version of deprecated ``newline_with_copy_margin`` which should - compute the correct indentation of the inserted line. That is to say, indent - by 4 extra space after a function definition, class definition, context - manager... And dedent by 4 space after ``pass``, ``return``, ``raise ...``. - """ - - def newline_autoindent(event): - """insert a newline after the cursor indented appropriately.""" - b = event.current_buffer - d = b.document - - if b.complete_state: - b.cancel_completion() - text = d.text[:d.cursor_position] + '\n' - _, indent = inputsplitter.check_complete(text) - b.insert_text('\n' + (' ' * (indent or 0)), move_cursor=False) - - return newline_autoindent - - -def open_input_in_editor(event): - event.app.current_buffer.open_in_editor() - - -if sys.platform == 'win32': - from IPython.core.error import TryNext - from IPython.lib.clipboard import (ClipboardEmpty, - win32_clipboard_get, - tkinter_clipboard_get) - - @undoc - def win_paste(event): - try: - text = win32_clipboard_get() - except TryNext: - try: - text = tkinter_clipboard_get() - except (TryNext, ClipboardEmpty): - return - except ClipboardEmpty: - return - event.current_buffer.insert_text(text.replace("\t", " " * 4)) diff --git a/contrib/python/ipython/py3/IPython/testing/__init__.py b/contrib/python/ipython/py3/IPython/testing/__init__.py deleted file mode 100644 index 8fcd65ea41..0000000000 --- a/contrib/python/ipython/py3/IPython/testing/__init__.py +++ /dev/null @@ -1,20 +0,0 @@ -"""Testing support (tools to test IPython itself). -""" - -#----------------------------------------------------------------------------- -# Copyright (C) 2009-2011 The IPython Development Team -# -# Distributed under the terms of the BSD License. The full license is in -# the file COPYING, distributed as part of this software. -#----------------------------------------------------------------------------- - - -import os - -#----------------------------------------------------------------------------- -# Constants -#----------------------------------------------------------------------------- - -# We scale all timeouts via this factor, slow machines can increase it -IPYTHON_TESTING_TIMEOUT_SCALE = float(os.getenv( - 'IPYTHON_TESTING_TIMEOUT_SCALE', 1)) diff --git a/contrib/python/ipython/py3/IPython/testing/decorators.py b/contrib/python/ipython/py3/IPython/testing/decorators.py deleted file mode 100644 index 644a513a8c..0000000000 --- a/contrib/python/ipython/py3/IPython/testing/decorators.py +++ /dev/null @@ -1,202 +0,0 @@ -# -*- coding: utf-8 -*- -"""Decorators for labeling test objects. - -Decorators that merely return a modified version of the original function -object are straightforward. Decorators that return a new function object need -to use nose.tools.make_decorator(original_function)(decorator) in returning the -decorator, in order to preserve metadata such as function name, setup and -teardown functions and so on - see nose.tools for more information. - -This module provides a set of useful decorators meant to be ready to use in -your own tests. See the bottom of the file for the ready-made ones, and if you -find yourself writing a new one that may be of generic use, add it here. - -Included decorators: - - -Lightweight testing that remains unittest-compatible. - -- An @as_unittest decorator can be used to tag any normal parameter-less - function as a unittest TestCase. Then, both nose and normal unittest will - recognize it as such. This will make it easier to migrate away from Nose if - we ever need/want to while maintaining very lightweight tests. - -NOTE: This file contains IPython-specific decorators. Using the machinery in -IPython.external.decorators, we import either numpy.testing.decorators if numpy is -available, OR use equivalent code in IPython.external._decorators, which -we've copied verbatim from numpy. - -""" - -# Copyright (c) IPython Development Team. -# Distributed under the terms of the Modified BSD License. - -import os -import shutil -import sys -import tempfile -import unittest -import warnings -from importlib import import_module - -from decorator import decorator - -# Expose the unittest-driven decorators -from .ipunittest import ipdoctest, ipdocstring - -#----------------------------------------------------------------------------- -# Classes and functions -#----------------------------------------------------------------------------- - -# Simple example of the basic idea -def as_unittest(func): - """Decorator to make a simple function into a normal test via unittest.""" - class Tester(unittest.TestCase): - def test(self): - func() - - Tester.__name__ = func.__name__ - - return Tester - -# Utility functions - - -def skipif(skip_condition, msg=None): - """Make function raise SkipTest exception if skip_condition is true - - Parameters - ---------- - - skip_condition : bool or callable - Flag to determine whether to skip test. If the condition is a - callable, it is used at runtime to dynamically make the decision. This - is useful for tests that may require costly imports, to delay the cost - until the test suite is actually executed. - msg : string - Message to give on raising a SkipTest exception. - - Returns - ------- - decorator : function - Decorator, which, when applied to a function, causes SkipTest - to be raised when the skip_condition was True, and the function - to be called normally otherwise. - """ - if msg is None: - msg = "Test skipped due to test condition." - - import pytest - - assert isinstance(skip_condition, bool) - return pytest.mark.skipif(skip_condition, reason=msg) - - -# A version with the condition set to true, common case just to attach a message -# to a skip decorator -def skip(msg=None): - """Decorator factory - mark a test function for skipping from test suite. - - Parameters - ---------- - msg : string - Optional message to be added. - - Returns - ------- - decorator : function - Decorator, which, when applied to a function, causes SkipTest - to be raised, with the optional message added. - """ - if msg and not isinstance(msg, str): - raise ValueError('invalid object passed to `@skip` decorator, did you ' - 'meant `@skip()` with brackets ?') - return skipif(True, msg) - - -def onlyif(condition, msg): - """The reverse from skipif, see skipif for details.""" - - return skipif(not condition, msg) - -#----------------------------------------------------------------------------- -# Utility functions for decorators -def module_not_available(module): - """Can module be imported? Returns true if module does NOT import. - - This is used to make a decorator to skip tests that require module to be - available, but delay the 'import numpy' to test execution time. - """ - try: - mod = import_module(module) - mod_not_avail = False - except ImportError: - mod_not_avail = True - - return mod_not_avail - - -#----------------------------------------------------------------------------- -# Decorators for public use - -# Decorators to skip certain tests on specific platforms. -skip_win32 = skipif(sys.platform == 'win32', - "This test does not run under Windows") -skip_linux = skipif(sys.platform.startswith('linux'), - "This test does not run under Linux") -skip_osx = skipif(sys.platform == 'darwin',"This test does not run under OS X") - - -# Decorators to skip tests if not on specific platforms. -skip_if_not_win32 = skipif(sys.platform != 'win32', - "This test only runs under Windows") -skip_if_not_linux = skipif(not sys.platform.startswith('linux'), - "This test only runs under Linux") - -_x11_skip_cond = (sys.platform not in ('darwin', 'win32') and - os.environ.get('DISPLAY', '') == '') -_x11_skip_msg = "Skipped under *nix when X11/XOrg not available" - -skip_if_no_x11 = skipif(_x11_skip_cond, _x11_skip_msg) - -# Other skip decorators - -# generic skip without module -skip_without = lambda mod: skipif(module_not_available(mod), "This test requires %s" % mod) - -skipif_not_numpy = skip_without('numpy') - -skipif_not_matplotlib = skip_without('matplotlib') - -# A null 'decorator', useful to make more readable code that needs to pick -# between different decorators based on OS or other conditions -null_deco = lambda f: f - -# Some tests only run where we can use unicode paths. Note that we can't just -# check os.path.supports_unicode_filenames, which is always False on Linux. -try: - f = tempfile.NamedTemporaryFile(prefix=u"tmp€") -except UnicodeEncodeError: - unicode_paths = False -else: - unicode_paths = True - f.close() - -onlyif_unicode_paths = onlyif(unicode_paths, ("This test is only applicable " - "where we can use unicode in filenames.")) - - -def onlyif_cmds_exist(*commands): - """ - Decorator to skip test when at least one of `commands` is not found. - """ - assert ( - os.environ.get("IPTEST_WORKING_DIR", None) is None - ), "iptest deprecated since IPython 8.0" - for cmd in commands: - reason = f"This test runs only if command '{cmd}' is installed" - if not shutil.which(cmd): - import pytest - - return pytest.mark.skip(reason=reason) - return null_deco diff --git a/contrib/python/ipython/py3/IPython/testing/globalipapp.py b/contrib/python/ipython/py3/IPython/testing/globalipapp.py deleted file mode 100644 index 698e3d845a..0000000000 --- a/contrib/python/ipython/py3/IPython/testing/globalipapp.py +++ /dev/null @@ -1,115 +0,0 @@ -"""Global IPython app to support test running. - -We must start our own ipython object and heavily muck with it so that all the -modifications IPython makes to system behavior don't send the doctest machinery -into a fit. This code should be considered a gross hack, but it gets the job -done. -""" - -# Copyright (c) IPython Development Team. -# Distributed under the terms of the Modified BSD License. - -import builtins as builtin_mod -import sys -import types -import warnings - -from pathlib import Path - -from . import tools - -from IPython.core import page -from IPython.utils import io -from IPython.terminal.interactiveshell import TerminalInteractiveShell - - -def get_ipython(): - # This will get replaced by the real thing once we start IPython below - return start_ipython() - - -# A couple of methods to override those in the running IPython to interact -# better with doctest (doctest captures on raw stdout, so we need to direct -# various types of output there otherwise it will miss them). - -def xsys(self, cmd): - """Replace the default system call with a capturing one for doctest. - """ - # We use getoutput, but we need to strip it because pexpect captures - # the trailing newline differently from commands.getoutput - print(self.getoutput(cmd, split=False, depth=1).rstrip(), end='', file=sys.stdout) - sys.stdout.flush() - - -def _showtraceback(self, etype, evalue, stb): - """Print the traceback purely on stdout for doctest to capture it. - """ - print(self.InteractiveTB.stb2text(stb), file=sys.stdout) - - -def start_ipython(): - """Start a global IPython shell, which we need for IPython-specific syntax. - """ - global get_ipython - - # This function should only ever run once! - if hasattr(start_ipython, 'already_called'): - return - start_ipython.already_called = True - - # Store certain global objects that IPython modifies - _displayhook = sys.displayhook - _excepthook = sys.excepthook - _main = sys.modules.get('__main__') - - # Create custom argv and namespaces for our IPython to be test-friendly - config = tools.default_config() - config.TerminalInteractiveShell.simple_prompt = True - - # Create and initialize our test-friendly IPython instance. - shell = TerminalInteractiveShell.instance(config=config, - ) - - # A few more tweaks needed for playing nicely with doctests... - - # remove history file - shell.tempfiles.append(Path(config.HistoryManager.hist_file)) - - # These traps are normally only active for interactive use, set them - # permanently since we'll be mocking interactive sessions. - shell.builtin_trap.activate() - - # Modify the IPython system call with one that uses getoutput, so that we - # can capture subcommands and print them to Python's stdout, otherwise the - # doctest machinery would miss them. - shell.system = types.MethodType(xsys, shell) - - shell._showtraceback = types.MethodType(_showtraceback, shell) - - # IPython is ready, now clean up some global state... - - # Deactivate the various python system hooks added by ipython for - # interactive convenience so we don't confuse the doctest system - sys.modules['__main__'] = _main - sys.displayhook = _displayhook - sys.excepthook = _excepthook - - # So that ipython magics and aliases can be doctested (they work by making - # a call into a global _ip object). Also make the top-level get_ipython - # now return this without recursively calling here again. - _ip = shell - get_ipython = _ip.get_ipython - builtin_mod._ip = _ip - builtin_mod.ip = _ip - builtin_mod.get_ipython = get_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', '') - print(strng) - - page.orig_page = page.pager_page - page.pager_page = nopage - - return _ip diff --git a/contrib/python/ipython/py3/IPython/testing/ipunittest.py b/contrib/python/ipython/py3/IPython/testing/ipunittest.py deleted file mode 100644 index 5a940a5fe9..0000000000 --- a/contrib/python/ipython/py3/IPython/testing/ipunittest.py +++ /dev/null @@ -1,178 +0,0 @@ -"""Experimental code for cleaner support of IPython syntax with unittest. - -In IPython up until 0.10, we've used very hacked up nose machinery for running -tests with IPython special syntax, and this has proved to be extremely slow. -This module provides decorators to try a different approach, stemming from a -conversation Brian and I (FP) had about this problem Sept/09. - -The goal is to be able to easily write simple functions that can be seen by -unittest as tests, and ultimately for these to support doctests with full -IPython syntax. Nose already offers this based on naming conventions and our -hackish plugins, but we are seeking to move away from nose dependencies if -possible. - -This module follows a different approach, based on decorators. - -- A decorator called @ipdoctest can mark any function as having a docstring - that should be viewed as a doctest, but after syntax conversion. - -Authors -------- - -- Fernando Perez <Fernando.Perez@berkeley.edu> -""" - - -#----------------------------------------------------------------------------- -# Copyright (C) 2009-2011 The IPython Development Team -# -# Distributed under the terms of the BSD License. The full license is in -# the file COPYING, distributed as part of this software. -#----------------------------------------------------------------------------- - -#----------------------------------------------------------------------------- -# Imports -#----------------------------------------------------------------------------- - -# Stdlib -import re -import unittest -from doctest import DocTestFinder, DocTestRunner, TestResults -from IPython.terminal.interactiveshell import InteractiveShell - -#----------------------------------------------------------------------------- -# Classes and functions -#----------------------------------------------------------------------------- - -def count_failures(runner): - """Count number of failures in a doctest runner. - - Code modeled after the summarize() method in doctest. - """ - return [TestResults(f, t) for f, t in runner._name2ft.values() if f > 0 ] - - -class IPython2PythonConverter(object): - """Convert IPython 'syntax' to valid Python. - - Eventually this code may grow to be the full IPython syntax conversion - implementation, but for now it only does prompt conversion.""" - - def __init__(self): - self.rps1 = re.compile(r'In\ \[\d+\]: ') - self.rps2 = re.compile(r'\ \ \ \.\.\.+: ') - self.rout = re.compile(r'Out\[\d+\]: \s*?\n?') - self.pyps1 = '>>> ' - self.pyps2 = '... ' - self.rpyps1 = re.compile (r'(\s*%s)(.*)$' % self.pyps1) - self.rpyps2 = re.compile (r'(\s*%s)(.*)$' % self.pyps2) - - def __call__(self, ds): - """Convert IPython prompts to python ones in a string.""" - from . import globalipapp - - pyps1 = '>>> ' - pyps2 = '... ' - pyout = '' - - dnew = ds - dnew = self.rps1.sub(pyps1, dnew) - dnew = self.rps2.sub(pyps2, dnew) - dnew = self.rout.sub(pyout, dnew) - ip = InteractiveShell.instance() - - # Convert input IPython source into valid Python. - out = [] - newline = out.append - for line in dnew.splitlines(): - - mps1 = self.rpyps1.match(line) - if mps1 is not None: - prompt, text = mps1.groups() - newline(prompt+ip.prefilter(text, False)) - continue - - mps2 = self.rpyps2.match(line) - if mps2 is not None: - prompt, text = mps2.groups() - newline(prompt+ip.prefilter(text, True)) - continue - - newline(line) - newline('') # ensure a closing newline, needed by doctest - #print "PYSRC:", '\n'.join(out) # dbg - return '\n'.join(out) - - #return dnew - - -class Doc2UnitTester(object): - """Class whose instances act as a decorator for docstring testing. - - In practice we're only likely to need one instance ever, made below (though - no attempt is made at turning it into a singleton, there is no need for - that). - """ - def __init__(self, verbose=False): - """New decorator. - - Parameters - ---------- - - verbose : boolean, optional (False) - Passed to the doctest finder and runner to control verbosity. - """ - self.verbose = verbose - # We can reuse the same finder for all instances - self.finder = DocTestFinder(verbose=verbose, recurse=False) - - def __call__(self, func): - """Use as a decorator: doctest a function's docstring as a unittest. - - This version runs normal doctests, but the idea is to make it later run - ipython syntax instead.""" - - # Capture the enclosing instance with a different name, so the new - # class below can see it without confusion regarding its own 'self' - # that will point to the test instance at runtime - d2u = self - - # Rewrite the function's docstring to have python syntax - if func.__doc__ is not None: - func.__doc__ = ip2py(func.__doc__) - - # Now, create a tester object that is a real unittest instance, so - # normal unittest machinery (or Nose, or Trial) can find it. - class Tester(unittest.TestCase): - def test(self): - # Make a new runner per function to be tested - runner = DocTestRunner(verbose=d2u.verbose) - for the_test in d2u.finder.find(func, func.__name__): - runner.run(the_test) - failed = count_failures(runner) - if failed: - # Since we only looked at a single function's docstring, - # failed should contain at most one item. More than that - # is a case we can't handle and should error out on - if len(failed) > 1: - err = "Invalid number of test results: %s" % failed - raise ValueError(err) - # Report a normal failure. - self.fail('failed doctests: %s' % str(failed[0])) - - # Rename it so test reports have the original signature. - Tester.__name__ = func.__name__ - return Tester - - -def ipdocstring(func): - """Change the function docstring via ip2py. - """ - if func.__doc__ is not None: - func.__doc__ = ip2py(func.__doc__) - return func - - -# Make an instance of the classes for public use -ipdoctest = Doc2UnitTester() -ip2py = IPython2PythonConverter() diff --git a/contrib/python/ipython/py3/IPython/testing/plugin/README.txt b/contrib/python/ipython/py3/IPython/testing/plugin/README.txt deleted file mode 100644 index a85e5a12a1..0000000000 --- a/contrib/python/ipython/py3/IPython/testing/plugin/README.txt +++ /dev/null @@ -1,34 +0,0 @@ -======================================================= - Nose plugin with IPython and extension module support -======================================================= - -This directory provides the key functionality for test support that IPython -needs as a nose plugin, which can be installed for use in projects other than -IPython. - -The presence of a Makefile here is mostly for development and debugging -purposes as it only provides a few shorthand commands. You can manually -install the plugin by using standard Python procedures (``setup.py install`` -with appropriate arguments). - -To install the plugin using the Makefile, edit its first line to reflect where -you'd like the installation. - -Once you've set the prefix, simply build/install the plugin with:: - - make - -and run the tests with:: - - make test - -You should see output similar to:: - - maqroll[plugin]> make test - nosetests -s --with-ipdoctest --doctest-tests dtexample.py - .. - ---------------------------------------------------------------------- - Ran 2 tests in 0.016s - - OK - diff --git a/contrib/python/ipython/py3/IPython/testing/plugin/__init__.py b/contrib/python/ipython/py3/IPython/testing/plugin/__init__.py deleted file mode 100644 index e69de29bb2..0000000000 --- a/contrib/python/ipython/py3/IPython/testing/plugin/__init__.py +++ /dev/null diff --git a/contrib/python/ipython/py3/IPython/testing/plugin/dtexample.py b/contrib/python/ipython/py3/IPython/testing/plugin/dtexample.py deleted file mode 100644 index 68f7016e34..0000000000 --- a/contrib/python/ipython/py3/IPython/testing/plugin/dtexample.py +++ /dev/null @@ -1,167 +0,0 @@ -"""Simple example using doctests. - -This file just contains doctests both using plain python and IPython prompts. -All tests should be loaded by nose. -""" - -import os - - -def pyfunc(): - """Some pure python tests... - - >>> pyfunc() - 'pyfunc' - - >>> import os - - >>> 2+3 - 5 - - >>> for i in range(3): - ... print(i, end=' ') - ... print(i+1, end=' ') - ... - 0 1 1 2 2 3 - """ - return 'pyfunc' - -def ipfunc(): - """Some ipython tests... - - In [1]: import os - - In [3]: 2+3 - Out[3]: 5 - - In [26]: for i in range(3): - ....: print(i, end=' ') - ....: print(i+1, end=' ') - ....: - 0 1 1 2 2 3 - - - It's OK to use '_' for the last result, but do NOT try to use IPython's - numbered history of _NN outputs, since those won't exist under the - doctest environment: - - In [7]: 'hi' - Out[7]: 'hi' - - In [8]: print(repr(_)) - 'hi' - - In [7]: 3+4 - Out[7]: 7 - - In [8]: _+3 - Out[8]: 10 - - In [9]: ipfunc() - Out[9]: 'ipfunc' - """ - return "ipfunc" - - -def ipos(): - """Examples that access the operating system work: - - In [1]: !echo hello - hello - - In [2]: !echo hello > /tmp/foo_iptest - - In [3]: !cat /tmp/foo_iptest - hello - - In [4]: rm -f /tmp/foo_iptest - """ - pass - - -ipos.__skip_doctest__ = os.name == "nt" - - -def ranfunc(): - """A function with some random output. - - Normal examples are verified as usual: - >>> 1+3 - 4 - - But if you put '# random' in the output, it is ignored: - >>> 1+3 - junk goes here... # random - - >>> 1+2 - again, anything goes #random - if multiline, the random mark is only needed once. - - >>> 1+2 - You can also put the random marker at the end: - # random - - >>> 1+2 - # random - .. or at the beginning. - - More correct input is properly verified: - >>> ranfunc() - 'ranfunc' - """ - return 'ranfunc' - - -def random_all(): - """A function where we ignore the output of ALL examples. - - Examples: - - # all-random - - This mark tells the testing machinery that all subsequent examples should - be treated as random (ignoring their output). They are still executed, - so if a they raise an error, it will be detected as such, but their - output is completely ignored. - - >>> 1+3 - junk goes here... - - >>> 1+3 - klasdfj; - - >>> 1+2 - again, anything goes - blah... - """ - pass - -def iprand(): - """Some ipython tests with random output. - - In [7]: 3+4 - Out[7]: 7 - - In [8]: print('hello') - world # random - - In [9]: iprand() - Out[9]: 'iprand' - """ - return 'iprand' - -def iprand_all(): - """Some ipython tests with fully random output. - - # all-random - - In [7]: 1 - Out[7]: 99 - - In [8]: print('hello') - world - - In [9]: iprand_all() - Out[9]: 'junk' - """ - return 'iprand_all' diff --git a/contrib/python/ipython/py3/IPython/testing/plugin/ipdoctest.py b/contrib/python/ipython/py3/IPython/testing/plugin/ipdoctest.py deleted file mode 100644 index 52cd8fd3b8..0000000000 --- a/contrib/python/ipython/py3/IPython/testing/plugin/ipdoctest.py +++ /dev/null @@ -1,300 +0,0 @@ -"""Nose Plugin that supports IPython doctests. - -Limitations: - -- When generating examples for use as doctests, make sure that you have - pretty-printing OFF. This can be done either by setting the - ``PlainTextFormatter.pprint`` option in your configuration file to False, or - by interactively disabling it with %Pprint. This is required so that IPython - output matches that of normal Python, which is used by doctest for internal - execution. - -- Do not rely on specific prompt numbers for results (such as using - '_34==True', for example). For IPython tests run via an external process the - prompt numbers may be different, and IPython tests run as normal python code - won't even have these special _NN variables set at all. -""" - -#----------------------------------------------------------------------------- -# Module imports - -# From the standard library -import doctest -import logging -import os -import re - -from testpath import modified_env - -#----------------------------------------------------------------------------- -# Module globals and other constants -#----------------------------------------------------------------------------- - -log = logging.getLogger(__name__) - - -#----------------------------------------------------------------------------- -# Classes and functions -#----------------------------------------------------------------------------- - - -class DocTestFinder(doctest.DocTestFinder): - def _get_test(self, obj, name, module, globs, source_lines): - test = super()._get_test(obj, name, module, globs, source_lines) - - if bool(getattr(obj, "__skip_doctest__", False)) and test is not None: - for example in test.examples: - example.options[doctest.SKIP] = True - - return test - - -class IPDoctestOutputChecker(doctest.OutputChecker): - """Second-chance checker with support for random tests. - - If the default comparison doesn't pass, this checker looks in the expected - output string for flags that tell us to ignore the output. - """ - - random_re = re.compile(r'#\s*random\s+') - - def check_output(self, want, got, optionflags): - """Check output, accepting special markers embedded in the output. - - If the output didn't pass the default validation but the special string - '#random' is included, we accept it.""" - - # Let the original tester verify first, in case people have valid tests - # that happen to have a comment saying '#random' embedded in. - ret = doctest.OutputChecker.check_output(self, want, got, - optionflags) - if not ret and self.random_re.search(want): - #print >> sys.stderr, 'RANDOM OK:',want # dbg - return True - - return ret - - -# A simple subclassing of the original with a different class name, so we can -# distinguish and treat differently IPython examples from pure python ones. -class IPExample(doctest.Example): pass - - -class IPDocTestParser(doctest.DocTestParser): - """ - A class used to parse strings containing doctest examples. - - Note: This is a version modified to properly recognize IPython input and - convert any IPython examples into valid Python ones. - """ - # This regular expression is used to find doctest examples in a - # string. It defines three groups: `source` is the source code - # (including leading indentation and prompts); `indent` is the - # indentation of the first (PS1) line of the source code; and - # `want` is the expected output (including leading indentation). - - # Classic Python prompts or default IPython ones - _PS1_PY = r'>>>' - _PS2_PY = r'\.\.\.' - - _PS1_IP = r'In\ \[\d+\]:' - _PS2_IP = r'\ \ \ \.\.\.+:' - - _RE_TPL = r''' - # Source consists of a PS1 line followed by zero or more PS2 lines. - (?P<source> - (?:^(?P<indent> [ ]*) (?P<ps1> %s) .*) # PS1 line - (?:\n [ ]* (?P<ps2> %s) .*)*) # PS2 lines - \n? # a newline - # Want consists of any non-blank lines that do not start with PS1. - (?P<want> (?:(?![ ]*$) # Not a blank line - (?![ ]*%s) # Not a line starting with PS1 - (?![ ]*%s) # Not a line starting with PS2 - .*$\n? # But any other line - )*) - ''' - - _EXAMPLE_RE_PY = re.compile( _RE_TPL % (_PS1_PY,_PS2_PY,_PS1_PY,_PS2_PY), - re.MULTILINE | re.VERBOSE) - - _EXAMPLE_RE_IP = re.compile( _RE_TPL % (_PS1_IP,_PS2_IP,_PS1_IP,_PS2_IP), - re.MULTILINE | re.VERBOSE) - - # Mark a test as being fully random. In this case, we simply append the - # random marker ('#random') to each individual example's output. This way - # we don't need to modify any other code. - _RANDOM_TEST = re.compile(r'#\s*all-random\s+') - - def ip2py(self,source): - """Convert input IPython source into valid Python.""" - block = _ip.input_transformer_manager.transform_cell(source) - if len(block.splitlines()) == 1: - return _ip.prefilter(block) - else: - return block - - def parse(self, string, name='<string>'): - """ - Divide the given string into examples and intervening text, - and return them as a list of alternating Examples and strings. - Line numbers for the Examples are 0-based. The optional - argument `name` is a name identifying this string, and is only - used for error messages. - """ - - #print 'Parse string:\n',string # dbg - - string = string.expandtabs() - # If all lines begin with the same indentation, then strip it. - min_indent = self._min_indent(string) - if min_indent > 0: - string = '\n'.join([l[min_indent:] for l in string.split('\n')]) - - output = [] - charno, lineno = 0, 0 - - # We make 'all random' tests by adding the '# random' mark to every - # block of output in the test. - if self._RANDOM_TEST.search(string): - random_marker = '\n# random' - else: - random_marker = '' - - # Whether to convert the input from ipython to python syntax - ip2py = False - # Find all doctest examples in the string. First, try them as Python - # examples, then as IPython ones - terms = list(self._EXAMPLE_RE_PY.finditer(string)) - if terms: - # Normal Python example - Example = doctest.Example - else: - # It's an ipython example. - terms = list(self._EXAMPLE_RE_IP.finditer(string)) - Example = IPExample - ip2py = True - - for m in terms: - # Add the pre-example text to `output`. - output.append(string[charno:m.start()]) - # Update lineno (lines before this example) - lineno += string.count('\n', charno, m.start()) - # Extract info from the regexp match. - (source, options, want, exc_msg) = \ - self._parse_example(m, name, lineno,ip2py) - - # Append the random-output marker (it defaults to empty in most - # cases, it's only non-empty for 'all-random' tests): - want += random_marker - - # Create an Example, and add it to the list. - if not self._IS_BLANK_OR_COMMENT(source): - output.append(Example(source, want, exc_msg, - lineno=lineno, - indent=min_indent+len(m.group('indent')), - options=options)) - # Update lineno (lines inside this example) - lineno += string.count('\n', m.start(), m.end()) - # Update charno. - charno = m.end() - # Add any remaining post-example text to `output`. - output.append(string[charno:]) - return output - - def _parse_example(self, m, name, lineno,ip2py=False): - """ - Given a regular expression match from `_EXAMPLE_RE` (`m`), - return a pair `(source, want)`, where `source` is the matched - example's source code (with prompts and indentation stripped); - and `want` is the example's expected output (with indentation - stripped). - - `name` is the string's name, and `lineno` is the line number - where the example starts; both are used for error messages. - - Optional: - `ip2py`: if true, filter the input via IPython to convert the syntax - into valid python. - """ - - # Get the example's indentation level. - indent = len(m.group('indent')) - - # Divide source into lines; check that they're properly - # indented; and then strip their indentation & prompts. - source_lines = m.group('source').split('\n') - - # We're using variable-length input prompts - ps1 = m.group('ps1') - ps2 = m.group('ps2') - ps1_len = len(ps1) - - self._check_prompt_blank(source_lines, indent, name, lineno,ps1_len) - if ps2: - self._check_prefix(source_lines[1:], ' '*indent + ps2, name, lineno) - - source = '\n'.join([sl[indent+ps1_len+1:] for sl in source_lines]) - - if ip2py: - # Convert source input from IPython into valid Python syntax - source = self.ip2py(source) - - # Divide want into lines; check that it's properly indented; and - # then strip the indentation. Spaces before the last newline should - # be preserved, so plain rstrip() isn't good enough. - want = m.group('want') - want_lines = want.split('\n') - if len(want_lines) > 1 and re.match(r' *$', want_lines[-1]): - del want_lines[-1] # forget final newline & spaces after it - self._check_prefix(want_lines, ' '*indent, name, - lineno + len(source_lines)) - - # Remove ipython output prompt that might be present in the first line - want_lines[0] = re.sub(r'Out\[\d+\]: \s*?\n?','',want_lines[0]) - - want = '\n'.join([wl[indent:] for wl in want_lines]) - - # If `want` contains a traceback message, then extract it. - m = self._EXCEPTION_RE.match(want) - if m: - exc_msg = m.group('msg') - else: - exc_msg = None - - # Extract options from the source. - options = self._find_options(source, name, lineno) - - return source, options, want, exc_msg - - def _check_prompt_blank(self, lines, indent, name, lineno, ps1_len): - """ - Given the lines of a source string (including prompts and - leading indentation), check to make sure that every prompt is - followed by a space character. If any line is not followed by - a space character, then raise ValueError. - - Note: IPython-modified version which takes the input prompt length as a - parameter, so that prompts of variable length can be dealt with. - """ - space_idx = indent+ps1_len - min_len = space_idx+1 - for i, line in enumerate(lines): - if len(line) >= min_len and line[space_idx] != ' ': - raise ValueError('line %r of the docstring for %s ' - 'lacks blank after %s: %r' % - (lineno+i+1, name, - line[indent:space_idx], line)) - - -SKIP = doctest.register_optionflag('SKIP') - - -class IPDocTestRunner(doctest.DocTestRunner,object): - """Test runner that synchronizes the IPython namespace with test globals. - """ - - def run(self, test, compileflags=None, out=None, clear_globs=True): - # Override terminal size to standardise traceback format - with modified_env({'COLUMNS': '80', 'LINES': '24'}): - return super(IPDocTestRunner,self).run(test, - compileflags,out,clear_globs) diff --git a/contrib/python/ipython/py3/IPython/testing/plugin/pytest_ipdoctest.py b/contrib/python/ipython/py3/IPython/testing/plugin/pytest_ipdoctest.py deleted file mode 100644 index 809713d7c8..0000000000 --- a/contrib/python/ipython/py3/IPython/testing/plugin/pytest_ipdoctest.py +++ /dev/null @@ -1,860 +0,0 @@ -# Based on Pytest doctest.py -# Original license: -# The MIT License (MIT) -# -# Copyright (c) 2004-2021 Holger Krekel and others -"""Discover and run ipdoctests in modules and test files.""" -import builtins -import bdb -import inspect -import os -import platform -import sys -import traceback -import types -import warnings -from contextlib import contextmanager -from pathlib import Path -from typing import Any -from typing import Callable -from typing import Dict -from typing import Generator -from typing import Iterable -from typing import List -from typing import Optional -from typing import Pattern -from typing import Sequence -from typing import Tuple -from typing import Type -from typing import TYPE_CHECKING -from typing import Union - -import pytest -from _pytest import outcomes -from _pytest._code.code import ExceptionInfo -from _pytest._code.code import ReprFileLocation -from _pytest._code.code import TerminalRepr -from _pytest._io import TerminalWriter -from _pytest.compat import safe_getattr -from _pytest.config import Config -from _pytest.config.argparsing import Parser -from _pytest.fixtures import FixtureRequest -from _pytest.nodes import Collector -from _pytest.outcomes import OutcomeException -from _pytest.pathlib import fnmatch_ex -from _pytest.pathlib import import_path -from _pytest.python_api import approx -from _pytest.warning_types import PytestWarning - -if TYPE_CHECKING: - import doctest - -DOCTEST_REPORT_CHOICE_NONE = "none" -DOCTEST_REPORT_CHOICE_CDIFF = "cdiff" -DOCTEST_REPORT_CHOICE_NDIFF = "ndiff" -DOCTEST_REPORT_CHOICE_UDIFF = "udiff" -DOCTEST_REPORT_CHOICE_ONLY_FIRST_FAILURE = "only_first_failure" - -DOCTEST_REPORT_CHOICES = ( - DOCTEST_REPORT_CHOICE_NONE, - DOCTEST_REPORT_CHOICE_CDIFF, - DOCTEST_REPORT_CHOICE_NDIFF, - DOCTEST_REPORT_CHOICE_UDIFF, - DOCTEST_REPORT_CHOICE_ONLY_FIRST_FAILURE, -) - -# Lazy definition of runner class -RUNNER_CLASS = None -# Lazy definition of output checker class -CHECKER_CLASS: Optional[Type["IPDoctestOutputChecker"]] = None - - -def pytest_addoption(parser: Parser) -> None: - parser.addini( - "ipdoctest_optionflags", - "option flags for ipdoctests", - type="args", - default=["ELLIPSIS"], - ) - parser.addini( - "ipdoctest_encoding", "encoding used for ipdoctest files", default="utf-8" - ) - group = parser.getgroup("collect") - group.addoption( - "--ipdoctest-modules", - action="store_true", - default=False, - help="run ipdoctests in all .py modules", - dest="ipdoctestmodules", - ) - group.addoption( - "--ipdoctest-report", - type=str.lower, - default="udiff", - help="choose another output format for diffs on ipdoctest failure", - choices=DOCTEST_REPORT_CHOICES, - dest="ipdoctestreport", - ) - group.addoption( - "--ipdoctest-glob", - action="append", - default=[], - metavar="pat", - help="ipdoctests file matching pattern, default: test*.txt", - dest="ipdoctestglob", - ) - group.addoption( - "--ipdoctest-ignore-import-errors", - action="store_true", - default=False, - help="ignore ipdoctest ImportErrors", - dest="ipdoctest_ignore_import_errors", - ) - group.addoption( - "--ipdoctest-continue-on-failure", - action="store_true", - default=False, - help="for a given ipdoctest, continue to run after the first failure", - dest="ipdoctest_continue_on_failure", - ) - - -def pytest_unconfigure() -> None: - global RUNNER_CLASS - - RUNNER_CLASS = None - - -def pytest_collect_file( - file_path: Path, - parent: Collector, -) -> Optional[Union["IPDoctestModule", "IPDoctestTextfile"]]: - config = parent.config - if file_path.suffix == ".py": - if config.option.ipdoctestmodules and not any( - (_is_setup_py(file_path), _is_main_py(file_path)) - ): - mod: IPDoctestModule = IPDoctestModule.from_parent(parent, path=file_path) - return mod - elif _is_ipdoctest(config, file_path, parent): - txt: IPDoctestTextfile = IPDoctestTextfile.from_parent(parent, path=file_path) - return txt - return None - - -if int(pytest.__version__.split(".")[0]) < 7: - _collect_file = pytest_collect_file - - def pytest_collect_file( - path, - parent: Collector, - ) -> Optional[Union["IPDoctestModule", "IPDoctestTextfile"]]: - return _collect_file(Path(path), parent) - - _import_path = import_path - - def import_path(path, root): - import py.path - - return _import_path(py.path.local(path)) - - -def _is_setup_py(path: Path) -> bool: - if path.name != "setup.py": - return False - contents = path.read_bytes() - return b"setuptools" in contents or b"distutils" in contents - - -def _is_ipdoctest(config: Config, path: Path, parent: Collector) -> bool: - if path.suffix in (".txt", ".rst") and parent.session.isinitpath(path): - return True - globs = config.getoption("ipdoctestglob") or ["test*.txt"] - return any(fnmatch_ex(glob, path) for glob in globs) - - -def _is_main_py(path: Path) -> bool: - return path.name == "__main__.py" - - -class ReprFailDoctest(TerminalRepr): - def __init__( - self, reprlocation_lines: Sequence[Tuple[ReprFileLocation, Sequence[str]]] - ) -> None: - self.reprlocation_lines = reprlocation_lines - - def toterminal(self, tw: TerminalWriter) -> None: - for reprlocation, lines in self.reprlocation_lines: - for line in lines: - tw.line(line) - reprlocation.toterminal(tw) - - -class MultipleDoctestFailures(Exception): - def __init__(self, failures: Sequence["doctest.DocTestFailure"]) -> None: - super().__init__() - self.failures = failures - - -def _init_runner_class() -> Type["IPDocTestRunner"]: - import doctest - from .ipdoctest import IPDocTestRunner - - class PytestDoctestRunner(IPDocTestRunner): - """Runner to collect failures. - - Note that the out variable in this case is a list instead of a - stdout-like object. - """ - - def __init__( - self, - checker: Optional["IPDoctestOutputChecker"] = None, - verbose: Optional[bool] = None, - optionflags: int = 0, - continue_on_failure: bool = True, - ) -> None: - super().__init__(checker=checker, verbose=verbose, optionflags=optionflags) - self.continue_on_failure = continue_on_failure - - def report_failure( - self, - out, - test: "doctest.DocTest", - example: "doctest.Example", - got: str, - ) -> None: - failure = doctest.DocTestFailure(test, example, got) - if self.continue_on_failure: - out.append(failure) - else: - raise failure - - def report_unexpected_exception( - self, - out, - test: "doctest.DocTest", - example: "doctest.Example", - exc_info: Tuple[Type[BaseException], BaseException, types.TracebackType], - ) -> None: - if isinstance(exc_info[1], OutcomeException): - raise exc_info[1] - if isinstance(exc_info[1], bdb.BdbQuit): - outcomes.exit("Quitting debugger") - failure = doctest.UnexpectedException(test, example, exc_info) - if self.continue_on_failure: - out.append(failure) - else: - raise failure - - return PytestDoctestRunner - - -def _get_runner( - checker: Optional["IPDoctestOutputChecker"] = None, - verbose: Optional[bool] = None, - optionflags: int = 0, - continue_on_failure: bool = True, -) -> "IPDocTestRunner": - # We need this in order to do a lazy import on doctest - global RUNNER_CLASS - if RUNNER_CLASS is None: - RUNNER_CLASS = _init_runner_class() - # Type ignored because the continue_on_failure argument is only defined on - # PytestDoctestRunner, which is lazily defined so can't be used as a type. - return RUNNER_CLASS( # type: ignore - checker=checker, - verbose=verbose, - optionflags=optionflags, - continue_on_failure=continue_on_failure, - ) - - -class IPDoctestItem(pytest.Item): - def __init__( - self, - name: str, - parent: "Union[IPDoctestTextfile, IPDoctestModule]", - runner: Optional["IPDocTestRunner"] = None, - dtest: Optional["doctest.DocTest"] = None, - ) -> None: - super().__init__(name, parent) - self.runner = runner - self.dtest = dtest - self.obj = None - self.fixture_request: Optional[FixtureRequest] = None - - @classmethod - def from_parent( # type: ignore - cls, - parent: "Union[IPDoctestTextfile, IPDoctestModule]", - *, - name: str, - runner: "IPDocTestRunner", - dtest: "doctest.DocTest", - ): - # incompatible signature due to imposed limits on subclass - """The public named constructor.""" - return super().from_parent(name=name, parent=parent, runner=runner, dtest=dtest) - - def setup(self) -> None: - if self.dtest is not None: - self.fixture_request = _setup_fixtures(self) - globs = dict(getfixture=self.fixture_request.getfixturevalue) - for name, value in self.fixture_request.getfixturevalue( - "ipdoctest_namespace" - ).items(): - globs[name] = value - self.dtest.globs.update(globs) - - from .ipdoctest import IPExample - - if isinstance(self.dtest.examples[0], IPExample): - # for IPython examples *only*, we swap the globals with the ipython - # namespace, after updating it with the globals (which doctest - # fills with the necessary info from the module being tested). - self._user_ns_orig = {} - self._user_ns_orig.update(_ip.user_ns) - _ip.user_ns.update(self.dtest.globs) - # We must remove the _ key in the namespace, so that Python's - # doctest code sets it naturally - _ip.user_ns.pop("_", None) - _ip.user_ns["__builtins__"] = builtins - self.dtest.globs = _ip.user_ns - - def teardown(self) -> None: - from .ipdoctest import IPExample - - # Undo the test.globs reassignment we made - if isinstance(self.dtest.examples[0], IPExample): - self.dtest.globs = {} - _ip.user_ns.clear() - _ip.user_ns.update(self._user_ns_orig) - del self._user_ns_orig - - self.dtest.globs.clear() - - def runtest(self) -> None: - assert self.dtest is not None - assert self.runner is not None - _check_all_skipped(self.dtest) - self._disable_output_capturing_for_darwin() - failures: List["doctest.DocTestFailure"] = [] - - # exec(compile(..., "single", ...), ...) puts result in builtins._ - had_underscore_value = hasattr(builtins, "_") - underscore_original_value = getattr(builtins, "_", None) - - # Save our current directory and switch out to the one where the - # test was originally created, in case another doctest did a - # directory change. We'll restore this in the finally clause. - curdir = os.getcwd() - os.chdir(self.fspath.dirname) - try: - # Type ignored because we change the type of `out` from what - # ipdoctest expects. - self.runner.run(self.dtest, out=failures, clear_globs=False) # type: ignore[arg-type] - finally: - os.chdir(curdir) - if had_underscore_value: - setattr(builtins, "_", underscore_original_value) - elif hasattr(builtins, "_"): - delattr(builtins, "_") - - if failures: - raise MultipleDoctestFailures(failures) - - def _disable_output_capturing_for_darwin(self) -> None: - """Disable output capturing. Otherwise, stdout is lost to ipdoctest (pytest#985).""" - if platform.system() != "Darwin": - return - capman = self.config.pluginmanager.getplugin("capturemanager") - if capman: - capman.suspend_global_capture(in_=True) - out, err = capman.read_global_capture() - sys.stdout.write(out) - sys.stderr.write(err) - - # TODO: Type ignored -- breaks Liskov Substitution. - def repr_failure( # type: ignore[override] - self, - excinfo: ExceptionInfo[BaseException], - ) -> Union[str, TerminalRepr]: - import doctest - - failures: Optional[ - Sequence[Union[doctest.DocTestFailure, doctest.UnexpectedException]] - ] = None - if isinstance( - excinfo.value, (doctest.DocTestFailure, doctest.UnexpectedException) - ): - failures = [excinfo.value] - elif isinstance(excinfo.value, MultipleDoctestFailures): - failures = excinfo.value.failures - - if failures is None: - return super().repr_failure(excinfo) - - reprlocation_lines = [] - for failure in failures: - example = failure.example - test = failure.test - filename = test.filename - if test.lineno is None: - lineno = None - else: - lineno = test.lineno + example.lineno + 1 - message = type(failure).__name__ - # TODO: ReprFileLocation doesn't expect a None lineno. - reprlocation = ReprFileLocation(filename, lineno, message) # type: ignore[arg-type] - checker = _get_checker() - report_choice = _get_report_choice(self.config.getoption("ipdoctestreport")) - if lineno is not None: - assert failure.test.docstring is not None - lines = failure.test.docstring.splitlines(False) - # add line numbers to the left of the error message - assert test.lineno is not None - lines = [ - "%03d %s" % (i + test.lineno + 1, x) for (i, x) in enumerate(lines) - ] - # trim docstring error lines to 10 - lines = lines[max(example.lineno - 9, 0) : example.lineno + 1] - else: - lines = [ - "EXAMPLE LOCATION UNKNOWN, not showing all tests of that example" - ] - indent = ">>>" - for line in example.source.splitlines(): - lines.append(f"??? {indent} {line}") - indent = "..." - if isinstance(failure, doctest.DocTestFailure): - lines += checker.output_difference( - example, failure.got, report_choice - ).split("\n") - else: - inner_excinfo = ExceptionInfo.from_exc_info(failure.exc_info) - lines += ["UNEXPECTED EXCEPTION: %s" % repr(inner_excinfo.value)] - lines += [ - x.strip("\n") for x in traceback.format_exception(*failure.exc_info) - ] - reprlocation_lines.append((reprlocation, lines)) - return ReprFailDoctest(reprlocation_lines) - - def reportinfo(self) -> Tuple[Union["os.PathLike[str]", str], Optional[int], str]: - assert self.dtest is not None - return self.path, self.dtest.lineno, "[ipdoctest] %s" % self.name - - if int(pytest.__version__.split(".")[0]) < 7: - - @property - def path(self) -> Path: - return Path(self.fspath) - - -def _get_flag_lookup() -> Dict[str, int]: - import doctest - - return dict( - DONT_ACCEPT_TRUE_FOR_1=doctest.DONT_ACCEPT_TRUE_FOR_1, - DONT_ACCEPT_BLANKLINE=doctest.DONT_ACCEPT_BLANKLINE, - NORMALIZE_WHITESPACE=doctest.NORMALIZE_WHITESPACE, - ELLIPSIS=doctest.ELLIPSIS, - IGNORE_EXCEPTION_DETAIL=doctest.IGNORE_EXCEPTION_DETAIL, - COMPARISON_FLAGS=doctest.COMPARISON_FLAGS, - ALLOW_UNICODE=_get_allow_unicode_flag(), - ALLOW_BYTES=_get_allow_bytes_flag(), - NUMBER=_get_number_flag(), - ) - - -def get_optionflags(parent): - optionflags_str = parent.config.getini("ipdoctest_optionflags") - flag_lookup_table = _get_flag_lookup() - flag_acc = 0 - for flag in optionflags_str: - flag_acc |= flag_lookup_table[flag] - return flag_acc - - -def _get_continue_on_failure(config): - continue_on_failure = config.getvalue("ipdoctest_continue_on_failure") - if continue_on_failure: - # We need to turn off this if we use pdb since we should stop at - # the first failure. - if config.getvalue("usepdb"): - continue_on_failure = False - return continue_on_failure - - -class IPDoctestTextfile(pytest.Module): - obj = None - - def collect(self) -> Iterable[IPDoctestItem]: - import doctest - from .ipdoctest import IPDocTestParser - - # Inspired by doctest.testfile; ideally we would use it directly, - # but it doesn't support passing a custom checker. - encoding = self.config.getini("ipdoctest_encoding") - text = self.path.read_text(encoding) - filename = str(self.path) - name = self.path.name - globs = {"__name__": "__main__"} - - optionflags = get_optionflags(self) - - runner = _get_runner( - verbose=False, - optionflags=optionflags, - checker=_get_checker(), - continue_on_failure=_get_continue_on_failure(self.config), - ) - - parser = IPDocTestParser() - test = parser.get_doctest(text, globs, name, filename, 0) - if test.examples: - yield IPDoctestItem.from_parent( - self, name=test.name, runner=runner, dtest=test - ) - - if int(pytest.__version__.split(".")[0]) < 7: - - @property - def path(self) -> Path: - return Path(self.fspath) - - @classmethod - def from_parent( - cls, - parent, - *, - fspath=None, - path: Optional[Path] = None, - **kw, - ): - if path is not None: - import py.path - - fspath = py.path.local(path) - return super().from_parent(parent=parent, fspath=fspath, **kw) - - -def _check_all_skipped(test: "doctest.DocTest") -> None: - """Raise pytest.skip() if all examples in the given DocTest have the SKIP - option set.""" - import doctest - - all_skipped = all(x.options.get(doctest.SKIP, False) for x in test.examples) - if all_skipped: - pytest.skip("all docstests skipped by +SKIP option") - - -def _is_mocked(obj: object) -> bool: - """Return if an object is possibly a mock object by checking the - existence of a highly improbable attribute.""" - return ( - safe_getattr(obj, "pytest_mock_example_attribute_that_shouldnt_exist", None) - is not None - ) - - -@contextmanager -def _patch_unwrap_mock_aware() -> Generator[None, None, None]: - """Context manager which replaces ``inspect.unwrap`` with a version - that's aware of mock objects and doesn't recurse into them.""" - real_unwrap = inspect.unwrap - - def _mock_aware_unwrap( - func: Callable[..., Any], *, stop: Optional[Callable[[Any], Any]] = None - ) -> Any: - try: - if stop is None or stop is _is_mocked: - return real_unwrap(func, stop=_is_mocked) - _stop = stop - return real_unwrap(func, stop=lambda obj: _is_mocked(obj) or _stop(func)) - except Exception as e: - warnings.warn( - "Got %r when unwrapping %r. This is usually caused " - "by a violation of Python's object protocol; see e.g. " - "https://github.com/pytest-dev/pytest/issues/5080" % (e, func), - PytestWarning, - ) - raise - - inspect.unwrap = _mock_aware_unwrap - try: - yield - finally: - inspect.unwrap = real_unwrap - - -class IPDoctestModule(pytest.Module): - def collect(self) -> Iterable[IPDoctestItem]: - import doctest - from .ipdoctest import DocTestFinder, IPDocTestParser - - class MockAwareDocTestFinder(DocTestFinder): - """A hackish ipdoctest finder that overrides stdlib internals to fix a stdlib bug. - - https://github.com/pytest-dev/pytest/issues/3456 - https://bugs.python.org/issue25532 - """ - - def _find_lineno(self, obj, source_lines): - """Doctest code does not take into account `@property`, this - is a hackish way to fix it. https://bugs.python.org/issue17446 - - Wrapped Doctests will need to be unwrapped so the correct - line number is returned. This will be reported upstream. #8796 - """ - if isinstance(obj, property): - obj = getattr(obj, "fget", obj) - - if hasattr(obj, "__wrapped__"): - # Get the main obj in case of it being wrapped - obj = inspect.unwrap(obj) - - # Type ignored because this is a private function. - return super()._find_lineno( # type:ignore[misc] - obj, - source_lines, - ) - - def _find( - self, tests, obj, name, module, source_lines, globs, seen - ) -> None: - if _is_mocked(obj): - return - with _patch_unwrap_mock_aware(): - - # Type ignored because this is a private function. - super()._find( # type:ignore[misc] - tests, obj, name, module, source_lines, globs, seen - ) - - if self.path.name == "conftest.py": - if int(pytest.__version__.split(".")[0]) < 7: - module = self.config.pluginmanager._importconftest( - self.path, - self.config.getoption("importmode"), - ) - else: - module = self.config.pluginmanager._importconftest( - self.path, - self.config.getoption("importmode"), - rootpath=self.config.rootpath, - ) - else: - try: - module = import_path(self.path, root=self.config.rootpath) - except ImportError: - if self.config.getvalue("ipdoctest_ignore_import_errors"): - pytest.skip("unable to import module %r" % self.path) - else: - raise - # Uses internal doctest module parsing mechanism. - finder = MockAwareDocTestFinder(parser=IPDocTestParser()) - optionflags = get_optionflags(self) - runner = _get_runner( - verbose=False, - optionflags=optionflags, - checker=_get_checker(), - continue_on_failure=_get_continue_on_failure(self.config), - ) - - for test in finder.find(module, module.__name__): - if test.examples: # skip empty ipdoctests - yield IPDoctestItem.from_parent( - self, name=test.name, runner=runner, dtest=test - ) - - if int(pytest.__version__.split(".")[0]) < 7: - - @property - def path(self) -> Path: - return Path(self.fspath) - - @classmethod - def from_parent( - cls, - parent, - *, - fspath=None, - path: Optional[Path] = None, - **kw, - ): - if path is not None: - import py.path - - fspath = py.path.local(path) - return super().from_parent(parent=parent, fspath=fspath, **kw) - - -def _setup_fixtures(doctest_item: IPDoctestItem) -> FixtureRequest: - """Used by IPDoctestTextfile and IPDoctestItem to setup fixture information.""" - - def func() -> None: - pass - - doctest_item.funcargs = {} # type: ignore[attr-defined] - fm = doctest_item.session._fixturemanager - doctest_item._fixtureinfo = fm.getfixtureinfo( # type: ignore[attr-defined] - node=doctest_item, func=func, cls=None, funcargs=False - ) - fixture_request = FixtureRequest(doctest_item, _ispytest=True) - fixture_request._fillfixtures() - return fixture_request - - -def _init_checker_class() -> Type["IPDoctestOutputChecker"]: - import doctest - import re - from .ipdoctest import IPDoctestOutputChecker - - class LiteralsOutputChecker(IPDoctestOutputChecker): - # Based on doctest_nose_plugin.py from the nltk project - # (https://github.com/nltk/nltk) and on the "numtest" doctest extension - # by Sebastien Boisgerault (https://github.com/boisgera/numtest). - - _unicode_literal_re = re.compile(r"(\W|^)[uU]([rR]?[\'\"])", re.UNICODE) - _bytes_literal_re = re.compile(r"(\W|^)[bB]([rR]?[\'\"])", re.UNICODE) - _number_re = re.compile( - r""" - (?P<number> - (?P<mantissa> - (?P<integer1> [+-]?\d*)\.(?P<fraction>\d+) - | - (?P<integer2> [+-]?\d+)\. - ) - (?: - [Ee] - (?P<exponent1> [+-]?\d+) - )? - | - (?P<integer3> [+-]?\d+) - (?: - [Ee] - (?P<exponent2> [+-]?\d+) - ) - ) - """, - re.VERBOSE, - ) - - def check_output(self, want: str, got: str, optionflags: int) -> bool: - if super().check_output(want, got, optionflags): - return True - - allow_unicode = optionflags & _get_allow_unicode_flag() - allow_bytes = optionflags & _get_allow_bytes_flag() - allow_number = optionflags & _get_number_flag() - - if not allow_unicode and not allow_bytes and not allow_number: - return False - - def remove_prefixes(regex: Pattern[str], txt: str) -> str: - return re.sub(regex, r"\1\2", txt) - - if allow_unicode: - want = remove_prefixes(self._unicode_literal_re, want) - got = remove_prefixes(self._unicode_literal_re, got) - - if allow_bytes: - want = remove_prefixes(self._bytes_literal_re, want) - got = remove_prefixes(self._bytes_literal_re, got) - - if allow_number: - got = self._remove_unwanted_precision(want, got) - - return super().check_output(want, got, optionflags) - - def _remove_unwanted_precision(self, want: str, got: str) -> str: - wants = list(self._number_re.finditer(want)) - gots = list(self._number_re.finditer(got)) - if len(wants) != len(gots): - return got - offset = 0 - for w, g in zip(wants, gots): - fraction: Optional[str] = w.group("fraction") - exponent: Optional[str] = w.group("exponent1") - if exponent is None: - exponent = w.group("exponent2") - precision = 0 if fraction is None else len(fraction) - if exponent is not None: - precision -= int(exponent) - if float(w.group()) == approx(float(g.group()), abs=10 ** -precision): - # They're close enough. Replace the text we actually - # got with the text we want, so that it will match when we - # check the string literally. - got = ( - got[: g.start() + offset] + w.group() + got[g.end() + offset :] - ) - offset += w.end() - w.start() - (g.end() - g.start()) - return got - - return LiteralsOutputChecker - - -def _get_checker() -> "IPDoctestOutputChecker": - """Return a IPDoctestOutputChecker subclass that supports some - additional options: - - * ALLOW_UNICODE and ALLOW_BYTES options to ignore u'' and b'' - prefixes (respectively) in string literals. Useful when the same - ipdoctest should run in Python 2 and Python 3. - - * NUMBER to ignore floating-point differences smaller than the - precision of the literal number in the ipdoctest. - - An inner class is used to avoid importing "ipdoctest" at the module - level. - """ - global CHECKER_CLASS - if CHECKER_CLASS is None: - CHECKER_CLASS = _init_checker_class() - return CHECKER_CLASS() - - -def _get_allow_unicode_flag() -> int: - """Register and return the ALLOW_UNICODE flag.""" - import doctest - - return doctest.register_optionflag("ALLOW_UNICODE") - - -def _get_allow_bytes_flag() -> int: - """Register and return the ALLOW_BYTES flag.""" - import doctest - - return doctest.register_optionflag("ALLOW_BYTES") - - -def _get_number_flag() -> int: - """Register and return the NUMBER flag.""" - import doctest - - return doctest.register_optionflag("NUMBER") - - -def _get_report_choice(key: str) -> int: - """Return the actual `ipdoctest` module flag value. - - We want to do it as late as possible to avoid importing `ipdoctest` and all - its dependencies when parsing options, as it adds overhead and breaks tests. - """ - import doctest - - return { - DOCTEST_REPORT_CHOICE_UDIFF: doctest.REPORT_UDIFF, - DOCTEST_REPORT_CHOICE_CDIFF: doctest.REPORT_CDIFF, - DOCTEST_REPORT_CHOICE_NDIFF: doctest.REPORT_NDIFF, - DOCTEST_REPORT_CHOICE_ONLY_FIRST_FAILURE: doctest.REPORT_ONLY_FIRST_FAILURE, - DOCTEST_REPORT_CHOICE_NONE: 0, - }[key] - - -@pytest.fixture(scope="session") -def ipdoctest_namespace() -> Dict[str, Any]: - """Fixture that returns a :py:class:`dict` that will be injected into the - namespace of ipdoctests.""" - return dict() diff --git a/contrib/python/ipython/py3/IPython/testing/plugin/setup.py b/contrib/python/ipython/py3/IPython/testing/plugin/setup.py deleted file mode 100644 index a3281d30c8..0000000000 --- a/contrib/python/ipython/py3/IPython/testing/plugin/setup.py +++ /dev/null @@ -1,18 +0,0 @@ -#!/usr/bin/env python -"""A Nose plugin to support IPython doctests. -""" - -from setuptools import setup - -setup(name='IPython doctest plugin', - version='0.1', - author='The IPython Team', - description = 'Nose plugin to load IPython-extended doctests', - license = 'LGPL', - py_modules = ['ipdoctest'], - entry_points = { - 'nose.plugins.0.10': ['ipdoctest = ipdoctest:IPythonDoctest', - 'extdoctest = ipdoctest:ExtensionDoctest', - ], - }, - ) diff --git a/contrib/python/ipython/py3/IPython/testing/plugin/simple.py b/contrib/python/ipython/py3/IPython/testing/plugin/simple.py deleted file mode 100644 index 35fbfd2fbd..0000000000 --- a/contrib/python/ipython/py3/IPython/testing/plugin/simple.py +++ /dev/null @@ -1,44 +0,0 @@ -"""Simple example using doctests. - -This file just contains doctests both using plain python and IPython prompts. -All tests should be loaded by Pytest. -""" - -def pyfunc(): - """Some pure python tests... - - >>> pyfunc() - 'pyfunc' - - >>> import os - - >>> 2+3 - 5 - - >>> for i in range(3): - ... print(i, end=' ') - ... print(i+1, end=' ') - ... - 0 1 1 2 2 3 - """ - return 'pyfunc' - - -def ipyfunc(): - """Some IPython tests... - - In [1]: ipyfunc() - Out[1]: 'ipyfunc' - - In [2]: import os - - In [3]: 2+3 - Out[3]: 5 - - In [4]: for i in range(3): - ...: print(i, end=' ') - ...: print(i+1, end=' ') - ...: - Out[4]: 0 1 1 2 2 3 - """ - return "ipyfunc" diff --git a/contrib/python/ipython/py3/IPython/testing/plugin/simplevars.py b/contrib/python/ipython/py3/IPython/testing/plugin/simplevars.py deleted file mode 100644 index cac0b75312..0000000000 --- a/contrib/python/ipython/py3/IPython/testing/plugin/simplevars.py +++ /dev/null @@ -1,2 +0,0 @@ -x = 1 -print('x is:',x) diff --git a/contrib/python/ipython/py3/IPython/testing/plugin/test_combo.txt b/contrib/python/ipython/py3/IPython/testing/plugin/test_combo.txt deleted file mode 100644 index 6c8759f3e7..0000000000 --- a/contrib/python/ipython/py3/IPython/testing/plugin/test_combo.txt +++ /dev/null @@ -1,36 +0,0 @@ -======================= - Combo testing example -======================= - -This is a simple example that mixes ipython doctests:: - - In [1]: import code - - In [2]: 2**12 - Out[2]: 4096 - -with command-line example information that does *not* get executed:: - - $ mpirun -n 4 ipengine --controller-port=10000 --controller-ip=host0 - -and with literal examples of Python source code:: - - controller = dict(host='myhost', - engine_port=None, # default is 10105 - control_port=None, - ) - - # keys are hostnames, values are the number of engine on that host - engines = dict(node1=2, - node2=2, - node3=2, - node3=2, - ) - - # Force failure to detect that this test is being run. - 1/0 - -These source code examples are executed but no output is compared at all. An -error or failure is reported only if an exception is raised. - -NOTE: the execution of pure python blocks is not yet working! diff --git a/contrib/python/ipython/py3/IPython/testing/plugin/test_example.txt b/contrib/python/ipython/py3/IPython/testing/plugin/test_example.txt deleted file mode 100644 index f8b681eb4f..0000000000 --- a/contrib/python/ipython/py3/IPython/testing/plugin/test_example.txt +++ /dev/null @@ -1,24 +0,0 @@ -===================================== - Tests in example form - pure python -===================================== - -This file contains doctest examples embedded as code blocks, using normal -Python prompts. See the accompanying file for similar examples using IPython -prompts (you can't mix both types within one file). The following will be run -as a test:: - - >>> 1+1 - 2 - >>> print ("hello") - hello - -More than one example works:: - - >>> s="Hello World" - - >>> s.upper() - 'HELLO WORLD' - -but you should note that the *entire* test file is considered to be a single -test. Individual code blocks that fail are printed separately as ``example -failures``, but the whole file is still counted and reported as one test. diff --git a/contrib/python/ipython/py3/IPython/testing/plugin/test_exampleip.txt b/contrib/python/ipython/py3/IPython/testing/plugin/test_exampleip.txt deleted file mode 100644 index 96b1eae19f..0000000000 --- a/contrib/python/ipython/py3/IPython/testing/plugin/test_exampleip.txt +++ /dev/null @@ -1,30 +0,0 @@ -================================= - Tests in example form - IPython -================================= - -You can write text files with examples that use IPython prompts (as long as you -use the nose ipython doctest plugin), but you can not mix and match prompt -styles in a single file. That is, you either use all ``>>>`` prompts or all -IPython-style prompts. Your test suite *can* have both types, you just need to -put each type of example in a separate. Using IPython prompts, you can paste -directly from your session:: - - In [5]: s="Hello World" - - In [6]: s.upper() - Out[6]: 'HELLO WORLD' - -Another example:: - - In [8]: 1+3 - Out[8]: 4 - -Just like in IPython docstrings, you can use all IPython syntax and features:: - - In [9]: !echo hello - hello - - In [10]: a='hi' - - In [11]: !echo $a - hi diff --git a/contrib/python/ipython/py3/IPython/testing/plugin/test_ipdoctest.py b/contrib/python/ipython/py3/IPython/testing/plugin/test_ipdoctest.py deleted file mode 100644 index 2686172bb2..0000000000 --- a/contrib/python/ipython/py3/IPython/testing/plugin/test_ipdoctest.py +++ /dev/null @@ -1,92 +0,0 @@ -"""Tests for the ipdoctest machinery itself. - -Note: in a file named test_X, functions whose only test is their docstring (as -a doctest) and which have no test functionality of their own, should be called -'doctest_foo' instead of 'test_foo', otherwise they get double-counted (the -empty function call is counted as a test, which just inflates tests numbers -artificially). -""" - -def doctest_simple(): - """ipdoctest must handle simple inputs - - In [1]: 1 - Out[1]: 1 - - In [2]: print(1) - 1 - """ - -def doctest_multiline1(): - """The ipdoctest machinery must handle multiline examples gracefully. - - In [2]: for i in range(4): - ...: print(i) - ...: - 0 - 1 - 2 - 3 - """ - -def doctest_multiline2(): - """Multiline examples that define functions and print output. - - In [7]: def f(x): - ...: return x+1 - ...: - - In [8]: f(1) - Out[8]: 2 - - In [9]: def g(x): - ...: print('x is:',x) - ...: - - In [10]: g(1) - x is: 1 - - In [11]: g('hello') - x is: hello - """ - - -def doctest_multiline3(): - """Multiline examples with blank lines. - - In [12]: def h(x): - ....: if x>1: - ....: return x**2 - ....: # To leave a blank line in the input, you must mark it - ....: # with a comment character: - ....: # - ....: # otherwise the doctest parser gets confused. - ....: else: - ....: return -1 - ....: - - In [13]: h(5) - Out[13]: 25 - - In [14]: h(1) - Out[14]: -1 - - In [15]: h(0) - Out[15]: -1 - """ - - -def doctest_builtin_underscore(): - """Defining builtins._ should not break anything outside the doctest - while also should be working as expected inside the doctest. - - In [1]: import builtins - - In [2]: builtins._ = 42 - - In [3]: builtins._ - Out[3]: 42 - - In [4]: _ - Out[4]: 42 - """ diff --git a/contrib/python/ipython/py3/IPython/testing/plugin/test_refs.py b/contrib/python/ipython/py3/IPython/testing/plugin/test_refs.py deleted file mode 100644 index b92448be07..0000000000 --- a/contrib/python/ipython/py3/IPython/testing/plugin/test_refs.py +++ /dev/null @@ -1,39 +0,0 @@ -"""Some simple tests for the plugin while running scripts. -""" -# Module imports -# Std lib -import inspect - -# Our own - -#----------------------------------------------------------------------------- -# Testing functions - -def test_trivial(): - """A trivial passing test.""" - pass - -def doctest_run(): - """Test running a trivial script. - - In [13]: run simplevars.py - x is: 1 - """ - -def doctest_runvars(): - """Test that variables defined in scripts get loaded correctly via %run. - - In [13]: run simplevars.py - x is: 1 - - In [14]: x - Out[14]: 1 - """ - -def doctest_ivars(): - """Test that variables defined interactively are picked up. - In [5]: zz=1 - - In [6]: zz - Out[6]: 1 - """ diff --git a/contrib/python/ipython/py3/IPython/testing/skipdoctest.py b/contrib/python/ipython/py3/IPython/testing/skipdoctest.py deleted file mode 100644 index f440ea14b2..0000000000 --- a/contrib/python/ipython/py3/IPython/testing/skipdoctest.py +++ /dev/null @@ -1,19 +0,0 @@ -"""Decorators marks that a doctest should be skipped. - -The IPython.testing.decorators module triggers various extra imports, including -numpy and sympy if they're present. Since this decorator is used in core parts -of IPython, it's in a separate module so that running IPython doesn't trigger -those imports.""" - -# Copyright (C) IPython Development Team -# Distributed under the terms of the Modified BSD License. - - -def skip_doctest(f): - """Decorator - mark a function or method for skipping its doctest. - - This decorator allows you to mark a function whose docstring you wish to - omit from testing, while preserving the docstring for introspection, help, - etc.""" - f.__skip_doctest__ = True - return f diff --git a/contrib/python/ipython/py3/IPython/testing/tools.py b/contrib/python/ipython/py3/IPython/testing/tools.py deleted file mode 100644 index 2ff63a6d4a..0000000000 --- a/contrib/python/ipython/py3/IPython/testing/tools.py +++ /dev/null @@ -1,476 +0,0 @@ -"""Generic testing tools. - -Authors -------- -- Fernando Perez <Fernando.Perez@berkeley.edu> -""" - - -# Copyright (c) IPython Development Team. -# Distributed under the terms of the Modified BSD License. - -import os -from pathlib import Path -import re -import sys -import tempfile -import unittest - -from contextlib import contextmanager -from io import StringIO -from subprocess import Popen, PIPE -from unittest.mock import patch - -from traitlets.config.loader import Config -from IPython.utils.process import get_output_error_code -from IPython.utils.text import list_strings -from IPython.utils.io import temp_pyfile, Tee -from IPython.utils import py3compat - -from . import decorators as dec -from . import skipdoctest - - -# The docstring for full_path doctests differently on win32 (different path -# separator) so just skip the doctest there. The example remains informative. -doctest_deco = skipdoctest.skip_doctest if sys.platform == 'win32' else dec.null_deco - -@doctest_deco -def full_path(startPath,files): - """Make full paths for all the listed files, based on startPath. - - Only the base part of startPath is kept, since this routine is typically - used with a script's ``__file__`` variable as startPath. The base of startPath - is then prepended to all the listed files, forming the output list. - - Parameters - ---------- - startPath : string - Initial path to use as the base for the results. This path is split - using os.path.split() and only its first component is kept. - - files : string or list - One or more files. - - Examples - -------- - - >>> full_path('/foo/bar.py',['a.txt','b.txt']) - ['/foo/a.txt', '/foo/b.txt'] - - >>> full_path('/foo',['a.txt','b.txt']) - ['/a.txt', '/b.txt'] - - If a single file is given, the output is still a list:: - - >>> full_path('/foo','a.txt') - ['/a.txt'] - """ - - files = list_strings(files) - base = os.path.split(startPath)[0] - return [ os.path.join(base,f) for f in files ] - - -def parse_test_output(txt): - """Parse the output of a test run and return errors, failures. - - Parameters - ---------- - txt : str - Text output of a test run, assumed to contain a line of one of the - following forms:: - - 'FAILED (errors=1)' - 'FAILED (failures=1)' - 'FAILED (errors=1, failures=1)' - - Returns - ------- - nerr, nfail - number of errors and failures. - """ - - err_m = re.search(r'^FAILED \(errors=(\d+)\)', txt, re.MULTILINE) - if err_m: - nerr = int(err_m.group(1)) - nfail = 0 - return nerr, nfail - - fail_m = re.search(r'^FAILED \(failures=(\d+)\)', txt, re.MULTILINE) - if fail_m: - nerr = 0 - nfail = int(fail_m.group(1)) - return nerr, nfail - - both_m = re.search(r'^FAILED \(errors=(\d+), failures=(\d+)\)', txt, - re.MULTILINE) - if both_m: - nerr = int(both_m.group(1)) - nfail = int(both_m.group(2)) - return nerr, nfail - - # If the input didn't match any of these forms, assume no error/failures - return 0, 0 - - -# So nose doesn't think this is a test -parse_test_output.__test__ = False - - -def default_argv(): - """Return a valid default argv for creating testing instances of ipython""" - - return ['--quick', # so no config file is loaded - # Other defaults to minimize side effects on stdout - '--colors=NoColor', '--no-term-title','--no-banner', - '--autocall=0'] - - -def default_config(): - """Return a config object with good defaults for testing.""" - config = Config() - config.TerminalInteractiveShell.colors = 'NoColor' - config.TerminalTerminalInteractiveShell.term_title = False, - config.TerminalInteractiveShell.autocall = 0 - f = tempfile.NamedTemporaryFile(suffix=u'test_hist.sqlite', delete=False) - config.HistoryManager.hist_file = Path(f.name) - f.close() - config.HistoryManager.db_cache_size = 10000 - return config - - -def get_ipython_cmd(as_string=False): - """ - Return appropriate IPython command line name. By default, this will return - a list that can be used with subprocess.Popen, for example, but passing - `as_string=True` allows for returning the IPython command as a string. - - Parameters - ---------- - as_string: bool - Flag to allow to return the command as a string. - """ - ipython_cmd = [sys.executable, "-m", "IPython"] - - if as_string: - ipython_cmd = " ".join(ipython_cmd) - - return ipython_cmd - -def ipexec(fname, options=None, commands=()): - """Utility to call 'ipython filename'. - - Starts IPython with a minimal and safe configuration to make startup as fast - as possible. - - Note that this starts IPython in a subprocess! - - Parameters - ---------- - fname : str, Path - Name of file to be executed (should have .py or .ipy extension). - - options : optional, list - Extra command-line flags to be passed to IPython. - - commands : optional, list - Commands to send in on stdin - - Returns - ------- - ``(stdout, stderr)`` of ipython subprocess. - """ - __tracebackhide__ = True - - if options is None: - options = [] - - cmdargs = default_argv() + options - - test_dir = os.path.dirname(__file__) - - ipython_cmd = get_ipython_cmd() - # Absolute path for filename - full_fname = os.path.join(test_dir, fname) - full_cmd = ipython_cmd + cmdargs + ['--', full_fname] - env = os.environ.copy() - # FIXME: ignore all warnings in ipexec while we have shims - # should we keep suppressing warnings here, even after removing shims? - env['PYTHONWARNINGS'] = 'ignore' - # env.pop('PYTHONWARNINGS', None) # Avoid extraneous warnings appearing on stderr - # Prevent coloring under PyCharm ("\x1b[0m" at the end of the stdout) - env.pop("PYCHARM_HOSTED", None) - for k, v in env.items(): - # Debug a bizarre failure we've seen on Windows: - # TypeError: environment can only contain strings - if not isinstance(v, str): - print(k, v) - p = Popen(full_cmd, stdout=PIPE, stderr=PIPE, stdin=PIPE, env=env) - out, err = p.communicate(input=py3compat.encode('\n'.join(commands)) or None) - out, err = py3compat.decode(out), py3compat.decode(err) - # `import readline` causes 'ESC[?1034h' to be output sometimes, - # so strip that out before doing comparisons - if out: - out = re.sub(r'\x1b\[[^h]+h', '', out) - return out, err - - -def ipexec_validate(fname, expected_out, expected_err='', - options=None, commands=()): - """Utility to call 'ipython filename' and validate output/error. - - This function raises an AssertionError if the validation fails. - - Note that this starts IPython in a subprocess! - - Parameters - ---------- - fname : str, Path - Name of the file to be executed (should have .py or .ipy extension). - - expected_out : str - Expected stdout of the process. - - expected_err : optional, str - Expected stderr of the process. - - options : optional, list - Extra command-line flags to be passed to IPython. - - Returns - ------- - None - """ - __tracebackhide__ = True - - out, err = ipexec(fname, options, commands) - #print 'OUT', out # dbg - #print 'ERR', err # dbg - # If there are any errors, we must check those before stdout, as they may be - # more informative than simply having an empty stdout. - if err: - if expected_err: - assert "\n".join(err.strip().splitlines()) == "\n".join( - expected_err.strip().splitlines() - ) - else: - raise ValueError('Running file %r produced error: %r' % - (fname, err)) - # If no errors or output on stderr was expected, match stdout - assert "\n".join(out.strip().splitlines()) == "\n".join( - expected_out.strip().splitlines() - ) - - -class TempFileMixin(unittest.TestCase): - """Utility class to create temporary Python/IPython files. - - Meant as a mixin class for test cases.""" - - def mktmp(self, src, ext='.py'): - """Make a valid python temp file.""" - fname = temp_pyfile(src, ext) - if not hasattr(self, 'tmps'): - self.tmps=[] - self.tmps.append(fname) - self.fname = fname - - def tearDown(self): - # If the tmpfile wasn't made because of skipped tests, like in - # win32, there's nothing to cleanup. - if hasattr(self, 'tmps'): - for fname in self.tmps: - # If the tmpfile wasn't made because of skipped tests, like in - # win32, there's nothing to cleanup. - try: - os.unlink(fname) - except: - # On Windows, even though we close the file, we still can't - # delete it. I have no clue why - pass - - 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" - "Expected:\n" - " {2!r}\n" - "Got:\n" - " {3!r}\n") -def check_pairs(func, pairs): - """Utility function for the common case of checking a function with a - sequence of input/output pairs. - - Parameters - ---------- - func : callable - The function to be tested. Should accept a single argument. - pairs : iterable - A list of (input, expected_output) tuples. - - Returns - ------- - None. Raises an AssertionError if any output does not match the expected - value. - """ - __tracebackhide__ = True - - name = getattr(func, "func_name", getattr(func, "__name__", "<unknown>")) - for inp, expected in pairs: - out = func(inp) - assert out == expected, pair_fail_msg.format(name, inp, expected, out) - - -MyStringIO = StringIO - -_re_type = type(re.compile(r'')) - -notprinted_msg = """Did not find {0!r} in printed output (on {1}): -------- -{2!s} -------- -""" - -class AssertPrints(object): - """Context manager for testing that code prints certain text. - - Examples - -------- - >>> with AssertPrints("abc", suppress=False): - ... print("abcd") - ... print("def") - ... - abcd - def - """ - def __init__(self, s, channel='stdout', suppress=True): - self.s = s - if isinstance(self.s, (str, _re_type)): - self.s = [self.s] - self.channel = channel - self.suppress = suppress - - def __enter__(self): - self.orig_stream = getattr(sys, self.channel) - self.buffer = MyStringIO() - self.tee = Tee(self.buffer, channel=self.channel) - setattr(sys, self.channel, self.buffer if self.suppress else self.tee) - - def __exit__(self, etype, value, traceback): - __tracebackhide__ = True - - try: - if value is not None: - # If an error was raised, don't check anything else - return False - self.tee.flush() - setattr(sys, self.channel, self.orig_stream) - printed = self.buffer.getvalue() - for s in self.s: - if isinstance(s, _re_type): - assert s.search(printed), notprinted_msg.format(s.pattern, self.channel, printed) - else: - assert s in printed, notprinted_msg.format(s, self.channel, printed) - return False - finally: - self.tee.close() - -printed_msg = """Found {0!r} in printed output (on {1}): -------- -{2!s} -------- -""" - -class AssertNotPrints(AssertPrints): - """Context manager for checking that certain output *isn't* produced. - - Counterpart of AssertPrints""" - def __exit__(self, etype, value, traceback): - __tracebackhide__ = True - - try: - if value is not None: - # If an error was raised, don't check anything else - self.tee.close() - return False - self.tee.flush() - setattr(sys, self.channel, self.orig_stream) - printed = self.buffer.getvalue() - for s in self.s: - if isinstance(s, _re_type): - assert not s.search(printed),printed_msg.format( - s.pattern, self.channel, printed) - else: - assert s not in printed, printed_msg.format( - s, self.channel, printed) - return False - finally: - self.tee.close() - -@contextmanager -def mute_warn(): - from IPython.utils import warn - save_warn = warn.warn - warn.warn = lambda *a, **kw: None - try: - yield - finally: - warn.warn = save_warn - -@contextmanager -def make_tempfile(name): - """Create an empty, named, temporary file for the duration of the context.""" - open(name, "w", encoding="utf-8").close() - try: - yield - finally: - os.unlink(name) - -def fake_input(inputs): - """Temporarily replace the input() function to return the given values - - Use as a context manager: - - with fake_input(['result1', 'result2']): - ... - - Values are returned in order. If input() is called again after the last value - was used, EOFError is raised. - """ - it = iter(inputs) - def mock_input(prompt=''): - try: - return next(it) - except StopIteration as e: - raise EOFError('No more inputs given') from e - - return patch('builtins.input', mock_input) - -def help_output_test(subcommand=''): - """test that `ipython [subcommand] -h` works""" - cmd = get_ipython_cmd() + [subcommand, '-h'] - out, err, rc = get_output_error_code(cmd) - assert rc == 0, err - assert "Traceback" not in err - assert "Options" in out - assert "--help-all" in out - return out, err - - -def help_all_output_test(subcommand=''): - """test that `ipython [subcommand] --help-all` works""" - cmd = get_ipython_cmd() + [subcommand, '--help-all'] - out, err, rc = get_output_error_code(cmd) - assert rc == 0, err - assert "Traceback" not in err - assert "Options" in out - assert "Class" in out - return out, err - diff --git a/contrib/python/ipython/py3/IPython/utils/PyColorize.py b/contrib/python/ipython/py3/IPython/utils/PyColorize.py deleted file mode 100644 index 86bb9af4c1..0000000000 --- a/contrib/python/ipython/py3/IPython/utils/PyColorize.py +++ /dev/null @@ -1,331 +0,0 @@ -# -*- coding: utf-8 -*- -""" -Class and program to colorize python source code for ANSI terminals. - -Based on an HTML code highlighter by Jurgen Hermann found at: -http://aspn.activestate.com/ASPN/Cookbook/Python/Recipe/52298 - -Modifications by Fernando Perez (fperez@colorado.edu). - -Information on the original HTML highlighter follows: - -MoinMoin - Python Source Parser - -Title: Colorize Python source using the built-in tokenizer - -Submitter: Jurgen Hermann -Last Updated:2001/04/06 - -Version no:1.2 - -Description: - -This code is part of MoinMoin (http://moin.sourceforge.net/) and converts -Python source code to HTML markup, rendering comments, keywords, -operators, numeric and string literals in different colors. - -It shows how to use the built-in keyword, token and tokenize modules to -scan Python source code and re-emit it with no changes to its original -formatting (which is the hard part). -""" - -__all__ = ['ANSICodeColors', 'Parser'] - -_scheme_default = 'Linux' - - -# Imports -import keyword -import os -import sys -import token -import tokenize - -generate_tokens = tokenize.generate_tokens - -from IPython.utils.coloransi import TermColors, InputTermColors,ColorScheme, ColorSchemeTable -from .colorable import Colorable -from io import StringIO - -############################################################################# -### Python Source Parser (does Highlighting) -############################################################################# - -_KEYWORD = token.NT_OFFSET + 1 -_TEXT = token.NT_OFFSET + 2 - -#**************************************************************************** -# Builtin color schemes - -Colors = TermColors # just a shorthand - -# Build a few color schemes -NoColor = ColorScheme( - 'NoColor',{ - 'header' : Colors.NoColor, - token.NUMBER : Colors.NoColor, - token.OP : Colors.NoColor, - token.STRING : Colors.NoColor, - tokenize.COMMENT : Colors.NoColor, - token.NAME : Colors.NoColor, - token.ERRORTOKEN : Colors.NoColor, - - _KEYWORD : Colors.NoColor, - _TEXT : Colors.NoColor, - - 'in_prompt' : InputTermColors.NoColor, # Input prompt - 'in_number' : InputTermColors.NoColor, # Input prompt number - 'in_prompt2' : InputTermColors.NoColor, # Continuation prompt - 'in_normal' : InputTermColors.NoColor, # color off (usu. Colors.Normal) - - 'out_prompt' : Colors.NoColor, # Output prompt - 'out_number' : Colors.NoColor, # Output prompt number - - 'normal' : Colors.NoColor # color off (usu. Colors.Normal) - } ) - -LinuxColors = ColorScheme( - 'Linux',{ - 'header' : Colors.LightRed, - token.NUMBER : Colors.LightCyan, - token.OP : Colors.Yellow, - token.STRING : Colors.LightBlue, - tokenize.COMMENT : Colors.LightRed, - token.NAME : Colors.Normal, - token.ERRORTOKEN : Colors.Red, - - _KEYWORD : Colors.LightGreen, - _TEXT : Colors.Yellow, - - 'in_prompt' : InputTermColors.Green, - 'in_number' : InputTermColors.LightGreen, - 'in_prompt2' : InputTermColors.Green, - '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) - } ) - -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, - 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) - } ) - -# Build table of color schemes (needed by the parser) -ANSICodeColors = ColorSchemeTable([NoColor,LinuxColors,LightBGColors, NeutralColors], - _scheme_default) - -Undefined = object() - -class Parser(Colorable): - """ Format colored Python source. - """ - - 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) - - self.color_table = color_table if color_table else ANSICodeColors - self.out = out - self.pos = None - self.lines = None - self.raw = None - if not style: - self.style = self.default_style - else: - self.style = style - - - def format(self, raw, out=None, scheme=Undefined): - import warnings - if scheme is not Undefined: - warnings.warn('The `scheme` argument of IPython.utils.PyColorize:Parser.format is deprecated since IPython 6.0.' - 'It will have no effect. Set the parser `style` directly.', - stacklevel=2) - return self.format2(raw, out)[0] - - def format2(self, raw, out = None): - """ Parse and send the colored source. - - If out and scheme are not specified, the defaults (given to - constructor) are used. - - out should be a file-type object. Optionally, out can be given as the - string 'str' and the parser will automatically return the output in a - string.""" - - string_output = 0 - if out == 'str' or self.out == 'str' or \ - isinstance(self.out, StringIO): - # XXX - I don't really like this state handling logic, but at this - # point I don't want to make major changes, so adding the - # isinstance() check is the simplest I can do to ensure correct - # behavior. - out_old = self.out - self.out = StringIO() - string_output = 1 - elif out is not None: - self.out = out - else: - raise ValueError('`out` or `self.out` should be file-like or the value `"str"`') - - # Fast return of the unmodified input for NoColor scheme - if self.style == 'NoColor': - error = False - self.out.write(raw) - if string_output: - return raw, error - return None, error - - # local shorthands - colors = self.color_table[self.style].colors - self.colors = colors # put in object so __call__ sees it - - # Remove trailing whitespace and normalize tabs - self.raw = raw.expandtabs().rstrip() - - # store line offsets in self.lines - self.lines = [0, 0] - pos = 0 - raw_find = self.raw.find - lines_append = self.lines.append - while True: - pos = raw_find('\n', pos) + 1 - if not pos: - break - lines_append(pos) - lines_append(len(self.raw)) - - # parse the source and write it - self.pos = 0 - text = StringIO(self.raw) - - error = False - try: - for atoken in generate_tokens(text.readline): - self(*atoken) - except tokenize.TokenError as ex: - msg = ex.args[0] - line = ex.args[1][0] - self.out.write("%s\n\n*** ERROR: %s%s%s\n" % - (colors[token.ERRORTOKEN], - msg, self.raw[self.lines[line]:], - colors.normal) - ) - error = True - self.out.write(colors.normal+'\n') - if string_output: - output = self.out.getvalue() - self.out = out_old - return (output, error) - return (None, error) - - - def _inner_call_(self, toktype, toktext, start_pos): - """like call but write to a temporary buffer""" - buff = StringIO() - srow, scol = start_pos - colors = self.colors - owrite = buff.write - - # line separator, so this works across platforms - linesep = os.linesep - - # calculate new positions - oldpos = self.pos - newpos = self.lines[srow] + scol - self.pos = newpos + len(toktext) - - # send the original whitespace, if needed - if newpos > oldpos: - owrite(self.raw[oldpos:newpos]) - - # skip indenting tokens - if toktype in [token.INDENT, token.DEDENT]: - self.pos = newpos - buff.seek(0) - return buff.read() - - # map token type to a color group - if token.LPAR <= toktype <= token.OP: - toktype = token.OP - elif toktype == token.NAME and keyword.iskeyword(toktext): - toktype = _KEYWORD - color = colors.get(toktype, colors[_TEXT]) - - # Triple quoted strings must be handled carefully so that backtracking - # in pagers works correctly. We need color terminators on _each_ line. - if linesep in toktext: - toktext = toktext.replace(linesep, '%s%s%s' % - (colors.normal,linesep,color)) - - # send text - owrite('%s%s%s' % (color,toktext,colors.normal)) - buff.seek(0) - return buff.read() - - - def __call__(self, toktype, toktext, start_pos, end_pos, line): - """ Token handler, with syntax highlighting.""" - self.out.write( - self._inner_call_(toktype, toktext, start_pos)) diff --git a/contrib/python/ipython/py3/IPython/utils/__init__.py b/contrib/python/ipython/py3/IPython/utils/__init__.py deleted file mode 100644 index e69de29bb2..0000000000 --- a/contrib/python/ipython/py3/IPython/utils/__init__.py +++ /dev/null diff --git a/contrib/python/ipython/py3/IPython/utils/_process_cli.py b/contrib/python/ipython/py3/IPython/utils/_process_cli.py deleted file mode 100644 index 86e918a8d0..0000000000 --- a/contrib/python/ipython/py3/IPython/utils/_process_cli.py +++ /dev/null @@ -1,69 +0,0 @@ -"""cli-specific implementation of process utilities. - -cli - Common Language Infrastructure for IronPython. Code - can run on any operating system. Check os.name for os- - specific settings. - -This file is only meant to be imported by process.py, not by end-users. - -This file is largely untested. To become a full drop-in process -interface for IronPython will probably require you to help fill -in the details. -""" - -# Import cli libraries: -import clr -import System - -# Import Python libraries: -import os - -# Import IPython libraries: -from ._process_common import arg_split - - -def system(cmd): - """ - system(cmd) should work in a cli environment on Mac OSX, Linux, - and Windows - """ - psi = System.Diagnostics.ProcessStartInfo(cmd) - psi.RedirectStandardOutput = True - psi.RedirectStandardError = True - psi.WindowStyle = System.Diagnostics.ProcessWindowStyle.Normal - psi.UseShellExecute = False - # Start up process: - reg = System.Diagnostics.Process.Start(psi) - -def getoutput(cmd): - """ - getoutput(cmd) should work in a cli environment on Mac OSX, Linux, - and Windows - """ - psi = System.Diagnostics.ProcessStartInfo(cmd) - psi.RedirectStandardOutput = True - psi.RedirectStandardError = True - psi.WindowStyle = System.Diagnostics.ProcessWindowStyle.Normal - psi.UseShellExecute = False - # Start up process: - reg = System.Diagnostics.Process.Start(psi) - myOutput = reg.StandardOutput - output = myOutput.ReadToEnd() - myError = reg.StandardError - error = myError.ReadToEnd() - return output - -def check_pid(pid): - """ - Check if a process with the given PID (pid) exists - """ - try: - System.Diagnostics.Process.GetProcessById(pid) - # process with given pid is running - return True - except System.InvalidOperationException: - # process wasn't started by this object (but is running) - return True - except System.ArgumentException: - # process with given pid isn't running - return False diff --git a/contrib/python/ipython/py3/IPython/utils/_process_common.py b/contrib/python/ipython/py3/IPython/utils/_process_common.py deleted file mode 100644 index 2a0b828839..0000000000 --- a/contrib/python/ipython/py3/IPython/utils/_process_common.py +++ /dev/null @@ -1,210 +0,0 @@ -"""Common utilities for the various process_* implementations. - -This file is only meant to be imported by the platform-specific implementations -of subprocess utilities, and it contains tools that are common to all of them. -""" - -#----------------------------------------------------------------------------- -# Copyright (C) 2010-2011 The IPython Development Team -# -# Distributed under the terms of the BSD License. The full license is in -# the file COPYING, distributed as part of this software. -#----------------------------------------------------------------------------- - -#----------------------------------------------------------------------------- -# Imports -#----------------------------------------------------------------------------- -import subprocess -import shlex -import sys -import os - -from IPython.utils import py3compat - -#----------------------------------------------------------------------------- -# Function definitions -#----------------------------------------------------------------------------- - -def read_no_interrupt(p): - """Read from a pipe ignoring EINTR errors. - - This is necessary because when reading from pipes with GUI event loops - running in the background, often interrupts are raised that stop the - command from completing.""" - import errno - - try: - return p.read() - except IOError as err: - if err.errno != errno.EINTR: - raise - - -def process_handler(cmd, callback, stderr=subprocess.PIPE): - """Open a command in a shell subprocess and execute a callback. - - This function provides common scaffolding for creating subprocess.Popen() - calls. It creates a Popen object and then calls the callback with it. - - Parameters - ---------- - cmd : str or list - A command to be executed by the system, using :class:`subprocess.Popen`. - If a string is passed, it will be run in the system shell. If a list is - passed, it will be used directly as arguments. - callback : callable - A one-argument function that will be called with the Popen object. - stderr : file descriptor number, optional - By default this is set to ``subprocess.PIPE``, but you can also pass the - value ``subprocess.STDOUT`` to force the subprocess' stderr to go into - the same file descriptor as its stdout. This is useful to read stdout - and stderr combined in the order they are generated. - - Returns - ------- - The return value of the provided callback is returned. - """ - sys.stdout.flush() - 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, str) - # 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, - close_fds=close_fds) - - try: - out = callback(p) - except KeyboardInterrupt: - print('^C') - sys.stdout.flush() - sys.stderr.flush() - out = None - finally: - # Make really sure that we don't leave processes behind, in case the - # call above raises an exception - # We start by assuming the subprocess finished (to avoid NameErrors - # later depending on the path taken) - if p.returncode is None: - try: - p.terminate() - p.poll() - except OSError: - pass - # One last try on our way out - if p.returncode is None: - try: - p.kill() - except OSError: - pass - - return out - - -def getoutput(cmd): - """Run a command and return its stdout/stderr as a string. - - Parameters - ---------- - cmd : str or list - A command to be executed in the system shell. - - Returns - ------- - output : str - A string containing the combination of stdout and stderr from the - subprocess, in whatever order the subprocess originally wrote to its - file descriptors (so the order of the information in this string is the - correct order as would be seen if running the command in a terminal). - """ - out = process_handler(cmd, lambda p: p.communicate()[0], subprocess.STDOUT) - if out is None: - return '' - return py3compat.decode(out) - - -def getoutputerror(cmd): - """Return (standard output, standard error) of executing cmd in a shell. - - Accepts the same arguments as os.system(). - - Parameters - ---------- - cmd : str or list - A command to be executed in the system shell. - - Returns - ------- - stdout : str - stderr : str - """ - return get_output_error_code(cmd)[:2] - -def get_output_error_code(cmd): - """Return (standard output, standard error, return code) of executing cmd - in a shell. - - Accepts the same arguments as os.system(). - - Parameters - ---------- - cmd : str or list - A command to be executed in the system shell. - - Returns - ------- - stdout : str - stderr : str - returncode: int - """ - - out_err, p = process_handler(cmd, lambda p: (p.communicate(), p)) - if out_err is None: - return '', '', p.returncode - out, err = out_err - return py3compat.decode(out), py3compat.decode(err), p.returncode - -def arg_split(s, posix=False, strict=True): - """Split a command line's arguments in a shell-like manner. - - This is a modified version of the standard library's shlex.split() - function, but with a default of posix=False for splitting, so that quotes - in inputs are respected. - - if strict=False, then any errors shlex.split would raise will result in the - unparsed remainder being the last element of the list, rather than raising. - This is because we sometimes use arg_split to parse things other than - command-line args. - """ - - lex = shlex.shlex(s, posix=posix) - lex.whitespace_split = True - # Extract tokens, ensuring that things like leaving open quotes - # does not cause this to raise. This is important, because we - # sometimes pass Python source through this (e.g. %timeit f(" ")), - # and it shouldn't raise an exception. - # It may be a bad idea to parse things that are not command-line args - # through this function, but we do, so let's be safe about it. - lex.commenters='' #fix for GH-1269 - tokens = [] - while True: - try: - tokens.append(next(lex)) - except StopIteration: - break - except ValueError: - if strict: - raise - # couldn't parse, get remaining blob as last token - tokens.append(lex.token) - break - - return tokens diff --git a/contrib/python/ipython/py3/IPython/utils/_process_posix.py b/contrib/python/ipython/py3/IPython/utils/_process_posix.py deleted file mode 100644 index 59b5c23896..0000000000 --- a/contrib/python/ipython/py3/IPython/utils/_process_posix.py +++ /dev/null @@ -1,216 +0,0 @@ -"""Posix-specific implementation of process utilities. - -This file is only meant to be imported by process.py, not by end-users. -""" - -#----------------------------------------------------------------------------- -# Copyright (C) 2010-2011 The IPython Development Team -# -# Distributed under the terms of the BSD License. The full license is in -# the file COPYING, distributed as part of this software. -#----------------------------------------------------------------------------- - -#----------------------------------------------------------------------------- -# Imports -#----------------------------------------------------------------------------- - -# Stdlib -import errno -import os -import subprocess as sp -import sys - -import pexpect - -# Our own -from ._process_common import getoutput, arg_split -from IPython.utils.encoding import DEFAULT_ENCODING - -#----------------------------------------------------------------------------- -# Function definitions -#----------------------------------------------------------------------------- - -class ProcessHandler(object): - """Execute subprocesses under the control of pexpect. - """ - # Timeout in seconds to wait on each reading of the subprocess' output. - # This should not be set too low to avoid cpu overusage from our side, - # since we read in a loop whose period is controlled by this timeout. - read_timeout = 0.05 - - # Timeout to give a process if we receive SIGINT, between sending the - # SIGINT to the process and forcefully terminating it. - terminate_timeout = 0.2 - - # File object where stdout and stderr of the subprocess will be written - logfile = None - - # Shell to call for subprocesses to execute - _sh = None - - @property - def sh(self): - if self._sh is None: - shell_name = os.environ.get("SHELL", "sh") - self._sh = pexpect.which(shell_name) - if self._sh is None: - raise OSError('"{}" shell not found'.format(shell_name)) - - return self._sh - - def __init__(self, logfile=None, read_timeout=None, terminate_timeout=None): - """Arguments are used for pexpect calls.""" - self.read_timeout = (ProcessHandler.read_timeout if read_timeout is - None else read_timeout) - self.terminate_timeout = (ProcessHandler.terminate_timeout if - terminate_timeout is None else - terminate_timeout) - self.logfile = sys.stdout if logfile is None else logfile - - def getoutput(self, cmd): - """Run a command and return its stdout/stderr as a string. - - Parameters - ---------- - cmd : str - A command to be executed in the system shell. - - Returns - ------- - output : str - A string containing the combination of stdout and stderr from the - subprocess, in whatever order the subprocess originally wrote to its - file descriptors (so the order of the information in this string is the - correct order as would be seen if running the command in a terminal). - """ - try: - return pexpect.run(self.sh, args=['-c', cmd]).replace('\r\n', '\n') - except KeyboardInterrupt: - print('^C', file=sys.stderr, end='') - - def getoutput_pexpect(self, cmd): - """Run a command and return its stdout/stderr as a string. - - Parameters - ---------- - cmd : str - A command to be executed in the system shell. - - Returns - ------- - output : str - A string containing the combination of stdout and stderr from the - subprocess, in whatever order the subprocess originally wrote to its - file descriptors (so the order of the information in this string is the - correct order as would be seen if running the command in a terminal). - """ - try: - return pexpect.run(self.sh, args=['-c', cmd]).replace('\r\n', '\n') - except KeyboardInterrupt: - print('^C', file=sys.stderr, end='') - - def system(self, cmd): - """Execute a command in a subshell. - - Parameters - ---------- - cmd : str - A command to be executed in the system shell. - - Returns - ------- - int : child's exitstatus - """ - # Get likely encoding for the output. - enc = DEFAULT_ENCODING - - # Patterns to match on the output, for pexpect. We read input and - # allow either a short timeout or EOF - patterns = [pexpect.TIMEOUT, pexpect.EOF] - # the index of the EOF pattern in the list. - # even though we know it's 1, this call means we don't have to worry if - # we change the above list, and forget to change this value: - EOF_index = patterns.index(pexpect.EOF) - # The size of the output stored so far in the process output buffer. - # Since pexpect only appends to this buffer, each time we print we - # record how far we've printed, so that next time we only print *new* - # content from the buffer. - out_size = 0 - try: - # Since we're not really searching the buffer for text patterns, we - # can set pexpect's search window to be tiny and it won't matter. - # We only search for the 'patterns' timeout or EOF, which aren't in - # the text itself. - #child = pexpect.spawn(pcmd, searchwindowsize=1) - if hasattr(pexpect, 'spawnb'): - child = pexpect.spawnb(self.sh, args=['-c', cmd]) # Pexpect-U - else: - child = pexpect.spawn(self.sh, args=['-c', cmd]) # Vanilla Pexpect - flush = sys.stdout.flush - while True: - # res is the index of the pattern that caused the match, so we - # know whether we've finished (if we matched EOF) or not - res_idx = child.expect_list(patterns, self.read_timeout) - print(child.before[out_size:].decode(enc, 'replace'), end='') - flush() - if res_idx==EOF_index: - break - # Update the pointer to what we've already printed - out_size = len(child.before) - except KeyboardInterrupt: - # We need to send ^C to the process. The ascii code for '^C' is 3 - # (the character is known as ETX for 'End of Text', see - # curses.ascii.ETX). - child.sendline(chr(3)) - # Read and print any more output the program might produce on its - # way out. - try: - out_size = len(child.before) - child.expect_list(patterns, self.terminate_timeout) - print(child.before[out_size:].decode(enc, 'replace'), end='') - sys.stdout.flush() - except KeyboardInterrupt: - # Impatient users tend to type it multiple times - pass - finally: - # Ensure the subprocess really is terminated - child.terminate(force=True) - # add isalive check, to ensure exitstatus is set: - child.isalive() - - # We follow the subprocess pattern, returning either the exit status - # as a positive number, or the terminating signal as a negative - # number. - # on Linux, sh returns 128+n for signals terminating child processes on Linux - # on BSD (OS X), the signal code is set instead - if child.exitstatus is None: - # on WIFSIGNALED, pexpect sets signalstatus, leaving exitstatus=None - if child.signalstatus is None: - # this condition may never occur, - # but let's be certain we always return an integer. - return 0 - return -child.signalstatus - if child.exitstatus > 128: - return -(child.exitstatus - 128) - return child.exitstatus - - -# Make system() with a functional interface for outside use. Note that we use -# getoutput() from the _common utils, which is built on top of popen(). Using -# pexpect to get subprocess output produces difficult to parse output, since -# programs think they are talking to a tty and produce highly formatted output -# (ls is a good example) that makes them hard. -system = ProcessHandler().system - -def check_pid(pid): - try: - os.kill(pid, 0) - except OSError as err: - if err.errno == errno.ESRCH: - return False - elif err.errno == errno.EPERM: - # Don't have permission to signal the process - probably means it exists - return True - raise - else: - return True diff --git a/contrib/python/ipython/py3/IPython/utils/_process_win32.py b/contrib/python/ipython/py3/IPython/utils/_process_win32.py deleted file mode 100644 index 36fb092d7b..0000000000 --- a/contrib/python/ipython/py3/IPython/utils/_process_win32.py +++ /dev/null @@ -1,184 +0,0 @@ -"""Windows-specific implementation of process utilities. - -This file is only meant to be imported by process.py, not by end-users. -""" - -#----------------------------------------------------------------------------- -# Copyright (C) 2010-2011 The IPython Development Team -# -# Distributed under the terms of the BSD License. The full license is in -# the file COPYING, distributed as part of this software. -#----------------------------------------------------------------------------- - -#----------------------------------------------------------------------------- -# Imports -#----------------------------------------------------------------------------- - -# stdlib -import os -import sys -import ctypes -import time - -from ctypes import c_int, POINTER -from ctypes.wintypes import LPCWSTR, HLOCAL -from subprocess import STDOUT, TimeoutExpired -from threading import Thread - -# our own imports -from ._process_common import read_no_interrupt, process_handler, arg_split as py_arg_split -from . import py3compat -from .encoding import DEFAULT_ENCODING - -#----------------------------------------------------------------------------- -# Function definitions -#----------------------------------------------------------------------------- - -class AvoidUNCPath(object): - """A context manager to protect command execution from UNC paths. - - In the Win32 API, commands can't be invoked with the cwd being a UNC path. - This context manager temporarily changes directory to the 'C:' drive on - entering, and restores the original working directory on exit. - - The context manager returns the starting working directory *if* it made a - change and None otherwise, so that users can apply the necessary adjustment - to their system calls in the event of a change. - - Examples - -------- - :: - cmd = 'dir' - with AvoidUNCPath() as path: - if path is not None: - cmd = '"pushd %s &&"%s' % (path, cmd) - os.system(cmd) - """ - def __enter__(self): - self.path = os.getcwd() - self.is_unc_path = self.path.startswith(r"\\") - if self.is_unc_path: - # change to c drive (as cmd.exe cannot handle UNC addresses) - os.chdir("C:") - return self.path - else: - # We return None to signal that there was no change in the working - # directory - return None - - def __exit__(self, exc_type, exc_value, traceback): - if self.is_unc_path: - os.chdir(self.path) - - -def _system_body(p): - """Callback for _system.""" - enc = DEFAULT_ENCODING - - def stdout_read(): - for line in read_no_interrupt(p.stdout).splitlines(): - line = line.decode(enc, 'replace') - print(line, file=sys.stdout) - - def stderr_read(): - for line in read_no_interrupt(p.stderr).splitlines(): - line = line.decode(enc, 'replace') - print(line, file=sys.stderr) - - Thread(target=stdout_read).start() - Thread(target=stderr_read).start() - - # Wait to finish for returncode. Unfortunately, Python has a bug where - # wait() isn't interruptible (https://bugs.python.org/issue28168) so poll in - # a loop instead of just doing `return p.wait()`. - while True: - result = p.poll() - if result is None: - time.sleep(0.01) - else: - return result - - -def system(cmd): - """Win32 version of os.system() that works with network shares. - - Note that this implementation returns None, as meant for use in IPython. - - Parameters - ---------- - cmd : str or list - A command to be executed in the system shell. - - Returns - ------- - int : child process' exit code. - """ - # The controller provides interactivity with both - # stdin and stdout - #import _process_win32_controller - #_process_win32_controller.system(cmd) - - with AvoidUNCPath() as path: - if path is not None: - cmd = '"pushd %s &&"%s' % (path, cmd) - return process_handler(cmd, _system_body) - -def getoutput(cmd): - """Return standard output of executing cmd in a shell. - - Accepts the same arguments as os.system(). - - Parameters - ---------- - cmd : str or list - A command to be executed in the system shell. - - Returns - ------- - stdout : str - """ - - with AvoidUNCPath() as path: - if path is not None: - cmd = '"pushd %s &&"%s' % (path, cmd) - out = process_handler(cmd, lambda p: p.communicate()[0], STDOUT) - - if out is None: - out = b'' - return py3compat.decode(out) - -try: - CommandLineToArgvW = ctypes.windll.shell32.CommandLineToArgvW - CommandLineToArgvW.arg_types = [LPCWSTR, POINTER(c_int)] - CommandLineToArgvW.restype = POINTER(LPCWSTR) - LocalFree = ctypes.windll.kernel32.LocalFree - LocalFree.res_type = HLOCAL - LocalFree.arg_types = [HLOCAL] - - def arg_split(commandline, posix=False, strict=True): - """Split a command line's arguments in a shell-like manner. - - This is a special version for windows that use a ctypes call to CommandLineToArgvW - to do the argv splitting. The posix parameter is ignored. - - If strict=False, process_common.arg_split(...strict=False) is used instead. - """ - #CommandLineToArgvW returns path to executable if called with empty string. - if commandline.strip() == "": - return [] - if not strict: - # not really a cl-arg, fallback on _process_common - return py_arg_split(commandline, posix=posix, strict=strict) - argvn = c_int() - result_pointer = CommandLineToArgvW(py3compat.cast_unicode(commandline.lstrip()), ctypes.byref(argvn)) - result_array_type = LPCWSTR * argvn.value - result = [arg for arg in result_array_type.from_address(ctypes.addressof(result_pointer.contents))] - retval = LocalFree(result_pointer) - return result -except AttributeError: - arg_split = py_arg_split - -def check_pid(pid): - # OpenProcess returns 0 if no such process (of ours) exists - # positive int otherwise - return bool(ctypes.windll.kernel32.OpenProcess(1,0,pid)) diff --git a/contrib/python/ipython/py3/IPython/utils/_process_win32_controller.py b/contrib/python/ipython/py3/IPython/utils/_process_win32_controller.py deleted file mode 100644 index f8c2a057a8..0000000000 --- a/contrib/python/ipython/py3/IPython/utils/_process_win32_controller.py +++ /dev/null @@ -1,573 +0,0 @@ -"""Windows-specific implementation of process utilities with direct WinAPI. - -This file is meant to be used by process.py -""" - -#----------------------------------------------------------------------------- -# Copyright (C) 2010-2011 The IPython Development Team -# -# Distributed under the terms of the BSD License. The full license is in -# the file COPYING, distributed as part of this software. -#----------------------------------------------------------------------------- - - -# stdlib -import os, sys, threading -import ctypes, msvcrt - -# Win32 API types needed for the API calls -from ctypes import POINTER -from ctypes.wintypes import HANDLE, HLOCAL, LPVOID, WORD, DWORD, BOOL, \ - ULONG, LPCWSTR -LPDWORD = POINTER(DWORD) -LPHANDLE = POINTER(HANDLE) -ULONG_PTR = POINTER(ULONG) -class SECURITY_ATTRIBUTES(ctypes.Structure): - _fields_ = [("nLength", DWORD), - ("lpSecurityDescriptor", LPVOID), - ("bInheritHandle", BOOL)] -LPSECURITY_ATTRIBUTES = POINTER(SECURITY_ATTRIBUTES) -class STARTUPINFO(ctypes.Structure): - _fields_ = [("cb", DWORD), - ("lpReserved", LPCWSTR), - ("lpDesktop", LPCWSTR), - ("lpTitle", LPCWSTR), - ("dwX", DWORD), - ("dwY", DWORD), - ("dwXSize", DWORD), - ("dwYSize", DWORD), - ("dwXCountChars", DWORD), - ("dwYCountChars", DWORD), - ("dwFillAttribute", DWORD), - ("dwFlags", DWORD), - ("wShowWindow", WORD), - ("cbReserved2", WORD), - ("lpReserved2", LPVOID), - ("hStdInput", HANDLE), - ("hStdOutput", HANDLE), - ("hStdError", HANDLE)] -LPSTARTUPINFO = POINTER(STARTUPINFO) -class PROCESS_INFORMATION(ctypes.Structure): - _fields_ = [("hProcess", HANDLE), - ("hThread", HANDLE), - ("dwProcessId", DWORD), - ("dwThreadId", DWORD)] -LPPROCESS_INFORMATION = POINTER(PROCESS_INFORMATION) - -# Win32 API constants needed -ERROR_HANDLE_EOF = 38 -ERROR_BROKEN_PIPE = 109 -ERROR_NO_DATA = 232 -HANDLE_FLAG_INHERIT = 0x0001 -STARTF_USESTDHANDLES = 0x0100 -CREATE_SUSPENDED = 0x0004 -CREATE_NEW_CONSOLE = 0x0010 -CREATE_NO_WINDOW = 0x08000000 -STILL_ACTIVE = 259 -WAIT_TIMEOUT = 0x0102 -WAIT_FAILED = 0xFFFFFFFF -INFINITE = 0xFFFFFFFF -DUPLICATE_SAME_ACCESS = 0x00000002 -ENABLE_ECHO_INPUT = 0x0004 -ENABLE_LINE_INPUT = 0x0002 -ENABLE_PROCESSED_INPUT = 0x0001 - -# Win32 API functions needed -GetLastError = ctypes.windll.kernel32.GetLastError -GetLastError.argtypes = [] -GetLastError.restype = DWORD - -CreateFile = ctypes.windll.kernel32.CreateFileW -CreateFile.argtypes = [LPCWSTR, DWORD, DWORD, LPVOID, DWORD, DWORD, HANDLE] -CreateFile.restype = HANDLE - -CreatePipe = ctypes.windll.kernel32.CreatePipe -CreatePipe.argtypes = [POINTER(HANDLE), POINTER(HANDLE), - LPSECURITY_ATTRIBUTES, DWORD] -CreatePipe.restype = BOOL - -CreateProcess = ctypes.windll.kernel32.CreateProcessW -CreateProcess.argtypes = [LPCWSTR, LPCWSTR, LPSECURITY_ATTRIBUTES, - LPSECURITY_ATTRIBUTES, BOOL, DWORD, LPVOID, LPCWSTR, LPSTARTUPINFO, - LPPROCESS_INFORMATION] -CreateProcess.restype = BOOL - -GetExitCodeProcess = ctypes.windll.kernel32.GetExitCodeProcess -GetExitCodeProcess.argtypes = [HANDLE, LPDWORD] -GetExitCodeProcess.restype = BOOL - -GetCurrentProcess = ctypes.windll.kernel32.GetCurrentProcess -GetCurrentProcess.argtypes = [] -GetCurrentProcess.restype = HANDLE - -ResumeThread = ctypes.windll.kernel32.ResumeThread -ResumeThread.argtypes = [HANDLE] -ResumeThread.restype = DWORD - -ReadFile = ctypes.windll.kernel32.ReadFile -ReadFile.argtypes = [HANDLE, LPVOID, DWORD, LPDWORD, LPVOID] -ReadFile.restype = BOOL - -WriteFile = ctypes.windll.kernel32.WriteFile -WriteFile.argtypes = [HANDLE, LPVOID, DWORD, LPDWORD, LPVOID] -WriteFile.restype = BOOL - -GetConsoleMode = ctypes.windll.kernel32.GetConsoleMode -GetConsoleMode.argtypes = [HANDLE, LPDWORD] -GetConsoleMode.restype = BOOL - -SetConsoleMode = ctypes.windll.kernel32.SetConsoleMode -SetConsoleMode.argtypes = [HANDLE, DWORD] -SetConsoleMode.restype = BOOL - -FlushConsoleInputBuffer = ctypes.windll.kernel32.FlushConsoleInputBuffer -FlushConsoleInputBuffer.argtypes = [HANDLE] -FlushConsoleInputBuffer.restype = BOOL - -WaitForSingleObject = ctypes.windll.kernel32.WaitForSingleObject -WaitForSingleObject.argtypes = [HANDLE, DWORD] -WaitForSingleObject.restype = DWORD - -DuplicateHandle = ctypes.windll.kernel32.DuplicateHandle -DuplicateHandle.argtypes = [HANDLE, HANDLE, HANDLE, LPHANDLE, - DWORD, BOOL, DWORD] -DuplicateHandle.restype = BOOL - -SetHandleInformation = ctypes.windll.kernel32.SetHandleInformation -SetHandleInformation.argtypes = [HANDLE, DWORD, DWORD] -SetHandleInformation.restype = BOOL - -CloseHandle = ctypes.windll.kernel32.CloseHandle -CloseHandle.argtypes = [HANDLE] -CloseHandle.restype = BOOL - -CommandLineToArgvW = ctypes.windll.shell32.CommandLineToArgvW -CommandLineToArgvW.argtypes = [LPCWSTR, POINTER(ctypes.c_int)] -CommandLineToArgvW.restype = POINTER(LPCWSTR) - -LocalFree = ctypes.windll.kernel32.LocalFree -LocalFree.argtypes = [HLOCAL] -LocalFree.restype = HLOCAL - -class AvoidUNCPath(object): - """A context manager to protect command execution from UNC paths. - - In the Win32 API, commands can't be invoked with the cwd being a UNC path. - This context manager temporarily changes directory to the 'C:' drive on - entering, and restores the original working directory on exit. - - The context manager returns the starting working directory *if* it made a - change and None otherwise, so that users can apply the necessary adjustment - to their system calls in the event of a change. - - Examples - -------- - :: - cmd = 'dir' - with AvoidUNCPath() as path: - if path is not None: - cmd = '"pushd %s &&"%s' % (path, cmd) - os.system(cmd) - """ - def __enter__(self): - self.path = os.getcwd() - self.is_unc_path = self.path.startswith(r"\\") - if self.is_unc_path: - # change to c drive (as cmd.exe cannot handle UNC addresses) - os.chdir("C:") - return self.path - else: - # We return None to signal that there was no change in the working - # directory - return None - - def __exit__(self, exc_type, exc_value, traceback): - if self.is_unc_path: - os.chdir(self.path) - - -class Win32ShellCommandController(object): - """Runs a shell command in a 'with' context. - - This implementation is Win32-specific. - - Example: - # Runs the command interactively with default console stdin/stdout - with ShellCommandController('python -i') as scc: - scc.run() - - # Runs the command using the provided functions for stdin/stdout - def my_stdout_func(s): - # print or save the string 's' - write_to_stdout(s) - def my_stdin_func(): - # If input is available, return it as a string. - if input_available(): - return get_input() - # If no input available, return None after a short delay to - # keep from blocking. - else: - time.sleep(0.01) - return None - - with ShellCommandController('python -i') as scc: - scc.run(my_stdout_func, my_stdin_func) - """ - - def __init__(self, cmd, mergeout = True): - """Initializes the shell command controller. - - The cmd is the program to execute, and mergeout is - whether to blend stdout and stderr into one output - in stdout. Merging them together in this fashion more - reliably keeps stdout and stderr in the correct order - especially for interactive shell usage. - """ - self.cmd = cmd - self.mergeout = mergeout - - def __enter__(self): - cmd = self.cmd - mergeout = self.mergeout - - self.hstdout, self.hstdin, self.hstderr = None, None, None - self.piProcInfo = None - try: - p_hstdout, c_hstdout, p_hstderr, \ - c_hstderr, p_hstdin, c_hstdin = [None]*6 - - # SECURITY_ATTRIBUTES with inherit handle set to True - saAttr = SECURITY_ATTRIBUTES() - saAttr.nLength = ctypes.sizeof(saAttr) - saAttr.bInheritHandle = True - saAttr.lpSecurityDescriptor = None - - def create_pipe(uninherit): - """Creates a Windows pipe, which consists of two handles. - - The 'uninherit' parameter controls which handle is not - inherited by the child process. - """ - handles = HANDLE(), HANDLE() - if not CreatePipe(ctypes.byref(handles[0]), - ctypes.byref(handles[1]), ctypes.byref(saAttr), 0): - raise ctypes.WinError() - if not SetHandleInformation(handles[uninherit], - HANDLE_FLAG_INHERIT, 0): - raise ctypes.WinError() - return handles[0].value, handles[1].value - - p_hstdout, c_hstdout = create_pipe(uninherit=0) - # 'mergeout' signals that stdout and stderr should be merged. - # We do that by using one pipe for both of them. - if mergeout: - c_hstderr = HANDLE() - if not DuplicateHandle(GetCurrentProcess(), c_hstdout, - GetCurrentProcess(), ctypes.byref(c_hstderr), - 0, True, DUPLICATE_SAME_ACCESS): - raise ctypes.WinError() - else: - p_hstderr, c_hstderr = create_pipe(uninherit=0) - c_hstdin, p_hstdin = create_pipe(uninherit=1) - - # Create the process object - piProcInfo = PROCESS_INFORMATION() - siStartInfo = STARTUPINFO() - siStartInfo.cb = ctypes.sizeof(siStartInfo) - siStartInfo.hStdInput = c_hstdin - siStartInfo.hStdOutput = c_hstdout - siStartInfo.hStdError = c_hstderr - siStartInfo.dwFlags = STARTF_USESTDHANDLES - dwCreationFlags = CREATE_SUSPENDED | CREATE_NO_WINDOW # | CREATE_NEW_CONSOLE - - if not CreateProcess(None, - u"cmd.exe /c " + cmd, - None, None, True, dwCreationFlags, - None, None, ctypes.byref(siStartInfo), - ctypes.byref(piProcInfo)): - raise ctypes.WinError() - - # Close this process's versions of the child handles - CloseHandle(c_hstdin) - c_hstdin = None - CloseHandle(c_hstdout) - c_hstdout = None - if c_hstderr is not None: - CloseHandle(c_hstderr) - c_hstderr = None - - # Transfer ownership of the parent handles to the object - self.hstdin = p_hstdin - p_hstdin = None - self.hstdout = p_hstdout - p_hstdout = None - if not mergeout: - self.hstderr = p_hstderr - p_hstderr = None - self.piProcInfo = piProcInfo - - finally: - if p_hstdin: - CloseHandle(p_hstdin) - if c_hstdin: - CloseHandle(c_hstdin) - if p_hstdout: - CloseHandle(p_hstdout) - if c_hstdout: - CloseHandle(c_hstdout) - if p_hstderr: - CloseHandle(p_hstderr) - if c_hstderr: - CloseHandle(c_hstderr) - - return self - - def _stdin_thread(self, handle, hprocess, func, stdout_func): - exitCode = DWORD() - bytesWritten = DWORD(0) - while True: - #print("stdin thread loop start") - # Get the input string (may be bytes or unicode) - data = func() - - # None signals to poll whether the process has exited - if data is None: - #print("checking for process completion") - if not GetExitCodeProcess(hprocess, ctypes.byref(exitCode)): - raise ctypes.WinError() - if exitCode.value != STILL_ACTIVE: - return - # TESTING: Does zero-sized writefile help? - if not WriteFile(handle, "", 0, - ctypes.byref(bytesWritten), None): - raise ctypes.WinError() - continue - #print("\nGot str %s\n" % repr(data), file=sys.stderr) - - # Encode the string to the console encoding - if isinstance(data, unicode): #FIXME: Python3 - data = data.encode('utf_8') - - # What we have now must be a string of bytes - if not isinstance(data, str): #FIXME: Python3 - raise RuntimeError("internal stdin function string error") - - # An empty string signals EOF - if len(data) == 0: - return - - # In a windows console, sometimes the input is echoed, - # but sometimes not. How do we determine when to do this? - stdout_func(data) - # WriteFile may not accept all the data at once. - # Loop until everything is processed - while len(data) != 0: - #print("Calling writefile") - if not WriteFile(handle, data, len(data), - ctypes.byref(bytesWritten), None): - # This occurs at exit - if GetLastError() == ERROR_NO_DATA: - return - raise ctypes.WinError() - #print("Called writefile") - data = data[bytesWritten.value:] - - def _stdout_thread(self, handle, func): - # Allocate the output buffer - data = ctypes.create_string_buffer(4096) - while True: - bytesRead = DWORD(0) - if not ReadFile(handle, data, 4096, - ctypes.byref(bytesRead), None): - le = GetLastError() - if le == ERROR_BROKEN_PIPE: - return - else: - raise ctypes.WinError() - # FIXME: Python3 - s = data.value[0:bytesRead.value] - #print("\nv: %s" % repr(s), file=sys.stderr) - func(s.decode('utf_8', 'replace')) - - def run(self, stdout_func = None, stdin_func = None, stderr_func = None): - """Runs the process, using the provided functions for I/O. - - The function stdin_func should return strings whenever a - character or characters become available. - The functions stdout_func and stderr_func are called whenever - something is printed to stdout or stderr, respectively. - These functions are called from different threads (but not - concurrently, because of the GIL). - """ - if stdout_func is None and stdin_func is None and stderr_func is None: - return self._run_stdio() - - if stderr_func is not None and self.mergeout: - raise RuntimeError("Shell command was initiated with " - "merged stdin/stdout, but a separate stderr_func " - "was provided to the run() method") - - # Create a thread for each input/output handle - stdin_thread = None - threads = [] - if stdin_func: - stdin_thread = threading.Thread(target=self._stdin_thread, - args=(self.hstdin, self.piProcInfo.hProcess, - stdin_func, stdout_func)) - threads.append(threading.Thread(target=self._stdout_thread, - args=(self.hstdout, stdout_func))) - if not self.mergeout: - if stderr_func is None: - stderr_func = stdout_func - threads.append(threading.Thread(target=self._stdout_thread, - args=(self.hstderr, stderr_func))) - # Start the I/O threads and the process - if ResumeThread(self.piProcInfo.hThread) == 0xFFFFFFFF: - raise ctypes.WinError() - if stdin_thread is not None: - stdin_thread.start() - for thread in threads: - thread.start() - # Wait for the process to complete - if WaitForSingleObject(self.piProcInfo.hProcess, INFINITE) == \ - WAIT_FAILED: - raise ctypes.WinError() - # Wait for the I/O threads to complete - for thread in threads: - thread.join() - - # Wait for the stdin thread to complete - if stdin_thread is not None: - stdin_thread.join() - - def _stdin_raw_nonblock(self): - """Use the raw Win32 handle of sys.stdin to do non-blocking reads""" - # WARNING: This is experimental, and produces inconsistent results. - # It's possible for the handle not to be appropriate for use - # with WaitForSingleObject, among other things. - handle = msvcrt.get_osfhandle(sys.stdin.fileno()) - result = WaitForSingleObject(handle, 100) - if result == WAIT_FAILED: - raise ctypes.WinError() - elif result == WAIT_TIMEOUT: - print(".", end='') - return None - else: - data = ctypes.create_string_buffer(256) - bytesRead = DWORD(0) - print('?', end='') - - if not ReadFile(handle, data, 256, - ctypes.byref(bytesRead), None): - raise ctypes.WinError() - # This ensures the non-blocking works with an actual console - # Not checking the error, so the processing will still work with - # other handle types - FlushConsoleInputBuffer(handle) - - data = data.value - data = data.replace('\r\n', '\n') - data = data.replace('\r', '\n') - print(repr(data) + " ", end='') - return data - - def _stdin_raw_block(self): - """Use a blocking stdin read""" - # The big problem with the blocking read is that it doesn't - # exit when it's supposed to in all contexts. An extra - # key-press may be required to trigger the exit. - try: - data = sys.stdin.read(1) - data = data.replace('\r', '\n') - return data - except WindowsError as we: - if we.winerror == ERROR_NO_DATA: - # This error occurs when the pipe is closed - return None - else: - # Otherwise let the error propagate - raise we - - def _stdout_raw(self, s): - """Writes the string to stdout""" - print(s, end='', file=sys.stdout) - sys.stdout.flush() - - def _stderr_raw(self, s): - """Writes the string to stdout""" - print(s, end='', file=sys.stderr) - sys.stderr.flush() - - def _run_stdio(self): - """Runs the process using the system standard I/O. - - IMPORTANT: stdin needs to be asynchronous, so the Python - sys.stdin object is not used. Instead, - msvcrt.kbhit/getwch are used asynchronously. - """ - # Disable Line and Echo mode - #lpMode = DWORD() - #handle = msvcrt.get_osfhandle(sys.stdin.fileno()) - #if GetConsoleMode(handle, ctypes.byref(lpMode)): - # set_console_mode = True - # if not SetConsoleMode(handle, lpMode.value & - # ~(ENABLE_ECHO_INPUT | ENABLE_LINE_INPUT | ENABLE_PROCESSED_INPUT)): - # raise ctypes.WinError() - - if self.mergeout: - return self.run(stdout_func = self._stdout_raw, - stdin_func = self._stdin_raw_block) - else: - return self.run(stdout_func = self._stdout_raw, - stdin_func = self._stdin_raw_block, - stderr_func = self._stderr_raw) - - # Restore the previous console mode - #if set_console_mode: - # if not SetConsoleMode(handle, lpMode.value): - # raise ctypes.WinError() - - def __exit__(self, exc_type, exc_value, traceback): - if self.hstdin: - CloseHandle(self.hstdin) - self.hstdin = None - if self.hstdout: - CloseHandle(self.hstdout) - self.hstdout = None - if self.hstderr: - CloseHandle(self.hstderr) - self.hstderr = None - if self.piProcInfo is not None: - CloseHandle(self.piProcInfo.hProcess) - CloseHandle(self.piProcInfo.hThread) - self.piProcInfo = None - - -def system(cmd): - """Win32 version of os.system() that works with network shares. - - Note that this implementation returns None, as meant for use in IPython. - - Parameters - ---------- - cmd : str - A command to be executed in the system shell. - - Returns - ------- - None : we explicitly do NOT return the subprocess status code, as this - utility is meant to be used extensively in IPython, where any return value - would trigger : func:`sys.displayhook` calls. - """ - with AvoidUNCPath() as path: - if path is not None: - cmd = '"pushd %s &&"%s' % (path, cmd) - with Win32ShellCommandController(cmd) as scc: - scc.run() - - -if __name__ == "__main__": - print("Test starting!") - #system("cmd") - system("python -i") - print("Test finished!") diff --git a/contrib/python/ipython/py3/IPython/utils/_sysinfo.py b/contrib/python/ipython/py3/IPython/utils/_sysinfo.py deleted file mode 100644 index 4b2609959f..0000000000 --- a/contrib/python/ipython/py3/IPython/utils/_sysinfo.py +++ /dev/null @@ -1,2 +0,0 @@ -# GENERATED BY setup.py -commit = u"4396dd620" diff --git a/contrib/python/ipython/py3/IPython/utils/capture.py b/contrib/python/ipython/py3/IPython/utils/capture.py deleted file mode 100644 index 97b6336688..0000000000 --- a/contrib/python/ipython/py3/IPython/utils/capture.py +++ /dev/null @@ -1,170 +0,0 @@ -# encoding: utf-8 -"""IO capturing utilities.""" - -# Copyright (c) IPython Development Team. -# Distributed under the terms of the Modified BSD License. - - -import sys -from io import StringIO - -#----------------------------------------------------------------------------- -# Classes and functions -#----------------------------------------------------------------------------- - - -class RichOutput(object): - def __init__(self, data=None, metadata=None, transient=None, update=False): - self.data = data or {} - self.metadata = metadata or {} - self.transient = transient or {} - self.update = update - - def display(self): - from IPython.display import publish_display_data - publish_display_data(data=self.data, metadata=self.metadata, - transient=self.transient, update=self.update) - - def _repr_mime_(self, mime): - if mime not in self.data: - return - data = self.data[mime] - if mime in self.metadata: - return data, self.metadata[mime] - else: - return data - - def _repr_mimebundle_(self, include=None, exclude=None): - return self.data, self.metadata - - def _repr_html_(self): - return self._repr_mime_("text/html") - - def _repr_latex_(self): - return self._repr_mime_("text/latex") - - def _repr_json_(self): - return self._repr_mime_("application/json") - - def _repr_javascript_(self): - return self._repr_mime_("application/javascript") - - def _repr_png_(self): - return self._repr_mime_("image/png") - - def _repr_jpeg_(self): - return self._repr_mime_("image/jpeg") - - def _repr_svg_(self): - return self._repr_mime_("image/svg+xml") - - -class CapturedIO(object): - """Simple object for containing captured stdout/err and rich display StringIO objects - - Each instance `c` has three attributes: - - - ``c.stdout`` : standard output as a string - - ``c.stderr`` : standard error as a string - - ``c.outputs``: a list of rich display outputs - - Additionally, there's a ``c.show()`` method which will print all of the - above in the same order, and can be invoked simply via ``c()``. - """ - - def __init__(self, stdout, stderr, outputs=None): - self._stdout = stdout - self._stderr = stderr - if outputs is None: - outputs = [] - self._outputs = outputs - - def __str__(self): - return self.stdout - - @property - def stdout(self): - "Captured standard output" - if not self._stdout: - return '' - return self._stdout.getvalue() - - @property - def stderr(self): - "Captured standard error" - if not self._stderr: - return '' - return self._stderr.getvalue() - - @property - def outputs(self): - """A list of the captured rich display outputs, if any. - - If you have a CapturedIO object ``c``, these can be displayed in IPython - using:: - - from IPython.display import display - for o in c.outputs: - display(o) - """ - return [ RichOutput(**kargs) for kargs in self._outputs ] - - def show(self): - """write my output to sys.stdout/err as appropriate""" - sys.stdout.write(self.stdout) - sys.stderr.write(self.stderr) - sys.stdout.flush() - sys.stderr.flush() - for kargs in self._outputs: - RichOutput(**kargs).display() - - __call__ = show - - -class capture_output(object): - """context manager for capturing stdout/err""" - stdout = True - stderr = True - display = True - - def __init__(self, stdout=True, stderr=True, display=True): - self.stdout = stdout - self.stderr = stderr - self.display = display - self.shell = None - - def __enter__(self): - from IPython.core.getipython import get_ipython - from IPython.core.displaypub import CapturingDisplayPublisher - from IPython.core.displayhook import CapturingDisplayHook - - self.sys_stdout = sys.stdout - self.sys_stderr = sys.stderr - - if self.display: - self.shell = get_ipython() - if self.shell is None: - self.save_display_pub = None - self.display = False - - stdout = stderr = outputs = None - if self.stdout: - stdout = sys.stdout = StringIO() - if self.stderr: - stderr = sys.stderr = StringIO() - if self.display: - self.save_display_pub = self.shell.display_pub - self.shell.display_pub = CapturingDisplayPublisher() - outputs = self.shell.display_pub.outputs - self.save_display_hook = sys.displayhook - sys.displayhook = CapturingDisplayHook(shell=self.shell, - outputs=outputs) - - return CapturedIO(stdout, stderr, outputs) - - def __exit__(self, exc_type, exc_value, traceback): - sys.stdout = self.sys_stdout - sys.stderr = self.sys_stderr - if self.display and self.shell: - self.shell.display_pub = self.save_display_pub - sys.displayhook = self.save_display_hook diff --git a/contrib/python/ipython/py3/IPython/utils/colorable.py b/contrib/python/ipython/py3/IPython/utils/colorable.py deleted file mode 100644 index 1e3caef62b..0000000000 --- a/contrib/python/ipython/py3/IPython/utils/colorable.py +++ /dev/null @@ -1,25 +0,0 @@ -#***************************************************************************** -# 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. -#***************************************************************************** - -""" -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/py3/IPython/utils/coloransi.py b/contrib/python/ipython/py3/IPython/utils/coloransi.py deleted file mode 100644 index e331421802..0000000000 --- a/contrib/python/ipython/py3/IPython/utils/coloransi.py +++ /dev/null @@ -1,187 +0,0 @@ -# -*- coding: utf-8 -*- -"""Tools for coloring text in ANSI terminals. -""" - -#***************************************************************************** -# Copyright (C) 2002-2006 Fernando Perez. <fperez@colorado.edu> -# -# Distributed under the terms of the BSD License. The full license is in -# the file COPYING, distributed as part of this software. -#***************************************************************************** - -__all__ = ['TermColors','InputTermColors','ColorScheme','ColorSchemeTable'] - -import os - -from IPython.utils.ipstruct import Struct - -color_templates = ( - # Dark colors - ("Black" , "0;30"), - ("Red" , "0;31"), - ("Green" , "0;32"), - ("Brown" , "0;33"), - ("Blue" , "0;34"), - ("Purple" , "0;35"), - ("Cyan" , "0;36"), - ("LightGray" , "0;37"), - # Light colors - ("DarkGray" , "1;30"), - ("LightRed" , "1;31"), - ("LightGreen" , "1;32"), - ("Yellow" , "1;33"), - ("LightBlue" , "1;34"), - ("LightPurple" , "1;35"), - ("LightCyan" , "1;36"), - ("White" , "1;37"), - # Blinking colors. Probably should not be used in anything serious. - ("BlinkBlack" , "5;30"), - ("BlinkRed" , "5;31"), - ("BlinkGreen" , "5;32"), - ("BlinkYellow" , "5;33"), - ("BlinkBlue" , "5;34"), - ("BlinkPurple" , "5;35"), - ("BlinkCyan" , "5;36"), - ("BlinkLightGray", "5;37"), - ) - -def make_color_table(in_class): - """Build a set of color attributes in a class. - - Helper function for building the :class:`TermColors` and - :class`InputTermColors`. - """ - for name,value in color_templates: - setattr(in_class,name,in_class._base % value) - -class TermColors: - """Color escape sequences. - - This class defines the escape sequences for all the standard (ANSI?) - colors in terminals. Also defines a NoColor escape which is just the null - string, suitable for defining 'dummy' color schemes in terminals which get - confused by color escapes. - - This class should be used as a mixin for building color schemes.""" - - NoColor = '' # for color schemes in color-less terminals. - Normal = '\033[0m' # Reset normal coloring - _base = '\033[%sm' # Template for all other colors - -# Build the actual color table as a set of class attributes: -make_color_table(TermColors) - -class InputTermColors: - """Color escape sequences for input prompts. - - This class is similar to TermColors, but the escapes are wrapped in \001 - and \002 so that readline can properly know the length of each line and - can wrap lines accordingly. Use this class for any colored text which - needs to be used in input prompts, such as in calls to raw_input(). - - This class defines the escape sequences for all the standard (ANSI?) - colors in terminals. Also defines a NoColor escape which is just the null - string, suitable for defining 'dummy' color schemes in terminals which get - confused by color escapes. - - This class should be used as a mixin for building color schemes.""" - - NoColor = '' # for color schemes in color-less terminals. - - if os.name == 'nt' and os.environ.get('TERM','dumb') == 'emacs': - # (X)emacs on W32 gets confused with \001 and \002 so we remove them - Normal = '\033[0m' # Reset normal coloring - _base = '\033[%sm' # Template for all other colors - else: - Normal = '\001\033[0m\002' # Reset normal coloring - _base = '\001\033[%sm\002' # Template for all other colors - -# Build the actual color table as a set of class attributes: -make_color_table(InputTermColors) - -class NoColors: - """This defines all the same names as the colour classes, but maps them to - empty strings, so it can easily be substituted to turn off colours.""" - NoColor = '' - Normal = '' - -for name, value in color_templates: - setattr(NoColors, name, '') - -class ColorScheme: - """Generic color scheme class. Just a name and a Struct.""" - def __init__(self,__scheme_name_,colordict=None,**colormap): - self.name = __scheme_name_ - if colordict is None: - self.colors = Struct(**colormap) - else: - self.colors = Struct(colordict) - - def copy(self,name=None): - """Return a full copy of the object, optionally renaming it.""" - if name is None: - name = self.name - return ColorScheme(name, self.colors.dict()) - -class ColorSchemeTable(dict): - """General class to handle tables of color schemes. - - It's basically a dict of color schemes with a couple of shorthand - attributes and some convenient methods. - - active_scheme_name -> obvious - active_colors -> actual color table of the active scheme""" - - def __init__(self, scheme_list=None, default_scheme=''): - """Create a table of color schemes. - - The table can be created empty and manually filled or it can be - created with a list of valid color schemes AND the specification for - the default active scheme. - """ - - # create object attributes to be set later - self.active_scheme_name = '' - self.active_colors = None - - if scheme_list: - if default_scheme == '': - raise ValueError('you must specify the default color scheme') - for scheme in scheme_list: - self.add_scheme(scheme) - self.set_active_scheme(default_scheme) - - def copy(self): - """Return full copy of object""" - return ColorSchemeTable(self.values(),self.active_scheme_name) - - def add_scheme(self,new_scheme): - """Add a new color scheme to the table.""" - if not isinstance(new_scheme,ColorScheme): - raise ValueError('ColorSchemeTable only accepts ColorScheme instances') - self[new_scheme.name] = new_scheme - - def set_active_scheme(self,scheme,case_sensitive=0): - """Set the currently active scheme. - - Names are by default compared in a case-insensitive way, but this can - be changed by setting the parameter case_sensitive to true.""" - - scheme_names = list(self.keys()) - if case_sensitive: - valid_schemes = scheme_names - scheme_test = scheme - else: - valid_schemes = [s.lower() for s in scheme_names] - scheme_test = scheme.lower() - try: - scheme_idx = valid_schemes.index(scheme_test) - except ValueError as e: - raise ValueError('Unrecognized color scheme: ' + scheme + \ - '\nValid schemes: '+str(scheme_names).replace("'', ",'')) from e - else: - active = scheme_names[scheme_idx] - self.active_scheme_name = active - self.active_colors = self[active].colors - # Now allow using '' as an index for the current active scheme - self[''] = self[active] diff --git a/contrib/python/ipython/py3/IPython/utils/contexts.py b/contrib/python/ipython/py3/IPython/utils/contexts.py deleted file mode 100644 index 7f95d4419d..0000000000 --- a/contrib/python/ipython/py3/IPython/utils/contexts.py +++ /dev/null @@ -1,60 +0,0 @@ -# encoding: utf-8 -"""Miscellaneous context managers. -""" - -import warnings - -# Copyright (c) IPython Development Team. -# Distributed under the terms of the Modified BSD License. - -class preserve_keys(object): - """Preserve a set of keys in a dictionary. - - Upon entering the context manager the current values of the keys - will be saved. Upon exiting, the dictionary will be updated to - restore the original value of the preserved keys. Preserved keys - which did not exist when entering the context manager will be - deleted. - - Examples - -------- - - >>> d = {'a': 1, 'b': 2, 'c': 3} - >>> with preserve_keys(d, 'b', 'c', 'd'): - ... del d['a'] - ... del d['b'] # will be reset to 2 - ... d['c'] = None # will be reset to 3 - ... d['d'] = 4 # will be deleted - ... d['e'] = 5 - ... print(sorted(d.items())) - ... - [('c', None), ('d', 4), ('e', 5)] - >>> print(sorted(d.items())) - [('b', 2), ('c', 3), ('e', 5)] - """ - - def __init__(self, dictionary, *keys): - self.dictionary = dictionary - self.keys = keys - - def __enter__(self): - # Actions to perform upon exiting. - to_delete = [] - to_update = {} - - d = self.dictionary - for k in self.keys: - if k in d: - to_update[k] = d[k] - else: - to_delete.append(k) - - self.to_delete = to_delete - self.to_update = to_update - - def __exit__(self, *exc_info): - d = self.dictionary - - for k in self.to_delete: - d.pop(k, None) - d.update(self.to_update) diff --git a/contrib/python/ipython/py3/IPython/utils/daemonize.py b/contrib/python/ipython/py3/IPython/utils/daemonize.py deleted file mode 100644 index 44b4a2832e..0000000000 --- a/contrib/python/ipython/py3/IPython/utils/daemonize.py +++ /dev/null @@ -1,4 +0,0 @@ -from warnings import warn - -warn("IPython.utils.daemonize has moved to ipyparallel.apps.daemonize since IPython 4.0", DeprecationWarning, stacklevel=2) -from ipyparallel.apps.daemonize import daemonize diff --git a/contrib/python/ipython/py3/IPython/utils/data.py b/contrib/python/ipython/py3/IPython/utils/data.py deleted file mode 100644 index 433c90916c..0000000000 --- a/contrib/python/ipython/py3/IPython/utils/data.py +++ /dev/null @@ -1,30 +0,0 @@ -# encoding: utf-8 -"""Utilities for working with data structures like lists, dicts and tuples. -""" - -#----------------------------------------------------------------------------- -# Copyright (C) 2008-2011 The IPython Development Team -# -# Distributed under the terms of the BSD License. The full license is in -# the file COPYING, distributed as part of this software. -#----------------------------------------------------------------------------- - - -def uniq_stable(elems): - """uniq_stable(elems) -> list - - Return from an iterable, a list of all the unique elements in the input, - but maintaining the order in which they first appear. - - Note: All elements in the input must be hashable for this routine - to work, as it internally uses a set for efficiency reasons. - """ - seen = set() - return [x for x in elems if x not in seen and not seen.add(x)] - - -def chop(seq, size): - """Chop a sequence into chunks of the given size.""" - return [seq[i:i+size] for i in range(0,len(seq),size)] - - diff --git a/contrib/python/ipython/py3/IPython/utils/decorators.py b/contrib/python/ipython/py3/IPython/utils/decorators.py deleted file mode 100644 index 47791d7ca6..0000000000 --- a/contrib/python/ipython/py3/IPython/utils/decorators.py +++ /dev/null @@ -1,58 +0,0 @@ -# encoding: utf-8 -"""Decorators that don't go anywhere else. - -This module contains misc. decorators that don't really go with another module -in :mod:`IPython.utils`. Beore putting something here please see if it should -go into another topical module in :mod:`IPython.utils`. -""" - -#----------------------------------------------------------------------------- -# Copyright (C) 2008-2011 The IPython Development Team -# -# Distributed under the terms of the BSD License. The full license is in -# the file COPYING, distributed as part of this software. -#----------------------------------------------------------------------------- - -#----------------------------------------------------------------------------- -# Imports -#----------------------------------------------------------------------------- - -#----------------------------------------------------------------------------- -# Code -#----------------------------------------------------------------------------- - -def flag_calls(func): - """Wrap a function to detect and flag when it gets called. - - This is a decorator which takes a function and wraps it in a function with - a 'called' attribute. wrapper.called is initialized to False. - - The wrapper.called attribute is set to False right before each call to the - wrapped function, so if the call fails it remains False. After the call - completes, wrapper.called is set to True and the output is returned. - - Testing for truth in wrapper.called allows you to determine if a call to - func() was attempted and succeeded.""" - - # don't wrap twice - if hasattr(func, 'called'): - return func - - def wrapper(*args,**kw): - wrapper.called = False - out = func(*args,**kw) - wrapper.called = True - return out - - wrapper.called = False - wrapper.__doc__ = func.__doc__ - return wrapper - -def undoc(func): - """Mark a function or class as undocumented. - - This is found by inspecting the AST, so for now it must be used directly - as @undoc, not as e.g. @decorators.undoc - """ - return func - diff --git a/contrib/python/ipython/py3/IPython/utils/dir2.py b/contrib/python/ipython/py3/IPython/utils/dir2.py deleted file mode 100644 index 9f19b2dd84..0000000000 --- a/contrib/python/ipython/py3/IPython/utils/dir2.py +++ /dev/null @@ -1,84 +0,0 @@ -# encoding: utf-8 -"""A fancy version of Python's builtin :func:`dir` function. -""" - -# Copyright (c) IPython Development Team. -# Distributed under the terms of the Modified BSD License. - -import inspect -import types - - -def safe_hasattr(obj, attr): - """In recent versions of Python, hasattr() only catches AttributeError. - This catches all errors. - """ - try: - getattr(obj, attr) - return True - except: - return False - - -def dir2(obj): - """dir2(obj) -> list of strings - - Extended version of the Python builtin dir(), which does a few extra - checks. - - This version is guaranteed to return only a list of true strings, whereas - dir() returns anything that objects inject into themselves, even if they - are later not really valid for attribute access (many extension libraries - have such bugs). - """ - - # Start building the attribute list via dir(), and then complete it - # with a few extra special-purpose calls. - - try: - words = set(dir(obj)) - except Exception: - # TypeError: dir(obj) does not return a list - words = set() - - if safe_hasattr(obj, '__class__'): - words |= set(dir(obj.__class__)) - - # filter out non-string attributes which may be stuffed by dir() calls - # and poor coding in third-party modules - - words = [w for w in words if isinstance(w, str)] - return sorted(words) - - -def get_real_method(obj, name): - """Like getattr, but with a few extra sanity checks: - - - If obj is a class, ignore everything except class 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. - """ - 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 inspect.isclass(obj) and not isinstance(m, types.MethodType): - return None - - if callable(m): - return m - - return None diff --git a/contrib/python/ipython/py3/IPython/utils/encoding.py b/contrib/python/ipython/py3/IPython/utils/encoding.py deleted file mode 100644 index 651ee0c0b5..0000000000 --- a/contrib/python/ipython/py3/IPython/utils/encoding.py +++ /dev/null @@ -1,71 +0,0 @@ -# coding: utf-8 -""" -Utilities for dealing with text encodings -""" - -#----------------------------------------------------------------------------- -# Copyright (C) 2008-2012 The IPython Development Team -# -# Distributed under the terms of the BSD License. The full license is in -# the file COPYING, distributed as part of this software. -#----------------------------------------------------------------------------- - -#----------------------------------------------------------------------------- -# Imports -#----------------------------------------------------------------------------- -import sys -import locale -import warnings - -# to deal with the possibility of sys.std* not being a stream at all -def get_stream_enc(stream, default=None): - """Return the given stream's encoding or a default. - - There are cases where ``sys.std*`` might not actually be a stream, so - check for the encoding attribute prior to returning it, and return - a default if it doesn't exist or evaluates as False. ``default`` - is None if not provided. - """ - if not hasattr(stream, 'encoding') or not stream.encoding: - return default - else: - return stream.encoding - -# Less conservative replacement for sys.getdefaultencoding, that will try -# to match the environment. -# Defined here as central function, so if we find better choices, we -# won't need to make changes all over IPython. -def getdefaultencoding(prefer_stream=True): - """Return IPython's guess for the default encoding for bytes as text. - - If prefer_stream is True (default), asks for stdin.encoding first, - to match the calling Terminal, but that is often None for subprocesses. - - Then fall back on locale.getpreferredencoding(), - which should be a sensible platform default (that respects LANG environment), - and finally to sys.getdefaultencoding() which is the most conservative option, - and usually UTF8 as of Python 3. - """ - enc = None - if prefer_stream: - enc = get_stream_enc(sys.stdin) - if not enc or enc=='ascii': - try: - # There are reports of getpreferredencoding raising errors - # in some cases, which may well be fixed, but let's be conservative here. - enc = locale.getpreferredencoding() - except Exception: - pass - enc = enc or sys.getdefaultencoding() - # On windows `cp0` can be returned to indicate that there is no code page. - # Since cp0 is an invalid encoding return instead cp1252 which is the - # Western European default. - if enc == 'cp0': - warnings.warn( - "Invalid code page cp0 detected - using cp1252 instead." - "If cp1252 is incorrect please ensure a valid code page " - "is defined for the process.", RuntimeWarning) - return 'cp1252' - return enc - -DEFAULT_ENCODING = getdefaultencoding() diff --git a/contrib/python/ipython/py3/IPython/utils/eventful.py b/contrib/python/ipython/py3/IPython/utils/eventful.py deleted file mode 100644 index 661851ed37..0000000000 --- a/contrib/python/ipython/py3/IPython/utils/eventful.py +++ /dev/null @@ -1,6 +0,0 @@ - -from warnings import warn - -warn("IPython.utils.eventful has moved to traitlets.eventful", stacklevel=2) - -from traitlets.eventful import * diff --git a/contrib/python/ipython/py3/IPython/utils/frame.py b/contrib/python/ipython/py3/IPython/utils/frame.py deleted file mode 100644 index 808906bda8..0000000000 --- a/contrib/python/ipython/py3/IPython/utils/frame.py +++ /dev/null @@ -1,92 +0,0 @@ -# encoding: utf-8 -""" -Utilities for working with stack frames. -""" - -#----------------------------------------------------------------------------- -# Copyright (C) 2008-2011 The IPython Development Team -# -# Distributed under the terms of the BSD License. The full license is in -# the file COPYING, distributed as part of this software. -#----------------------------------------------------------------------------- - -#----------------------------------------------------------------------------- -# Imports -#----------------------------------------------------------------------------- - -import sys - -#----------------------------------------------------------------------------- -# Code -#----------------------------------------------------------------------------- - -def extract_vars(*names,**kw): - """Extract a set of variables by name from another frame. - - Parameters - ---------- - *names : str - One or more variable names which will be extracted from the caller's - frame. - **kw : integer, optional - How many frames in the stack to walk when looking for your variables. - The default is 0, which will use the frame where the call was made. - - Examples - -------- - :: - - In [2]: def func(x): - ...: y = 1 - ...: print(sorted(extract_vars('x','y').items())) - ...: - - In [3]: func('hello') - [('x', 'hello'), ('y', 1)] - """ - - depth = kw.get('depth',0) - - callerNS = sys._getframe(depth+1).f_locals - return dict((k,callerNS[k]) for k in names) - - -def extract_vars_above(*names): - """Extract a set of variables by name from another frame. - - Similar to extractVars(), but with a specified depth of 1, so that names - are extracted exactly from above the caller. - - This is simply a convenience function so that the very common case (for us) - of skipping exactly 1 frame doesn't have to construct a special dict for - keyword passing.""" - - callerNS = sys._getframe(2).f_locals - return dict((k,callerNS[k]) for k in names) - - -def debugx(expr,pre_msg=''): - """Print the value of an expression from the caller's frame. - - Takes an expression, evaluates it in the caller's frame and prints both - the given expression and the resulting value (as well as a debug mark - indicating the name of the calling function. The input must be of a form - suitable for eval(). - - An optional message can be passed, which will be prepended to the printed - expr->value pair.""" - - cf = sys._getframe(1) - print('[DBG:%s] %s%s -> %r' % (cf.f_code.co_name,pre_msg,expr, - eval(expr,cf.f_globals,cf.f_locals))) - - -# deactivate it by uncommenting the following line, which makes it a no-op -#def debugx(expr,pre_msg=''): pass - -def extract_module_locals(depth=0): - """Returns (module, locals) of the function `depth` frames away from the caller""" - f = sys._getframe(depth + 1) - global_ns = f.f_globals - module = sys.modules[global_ns['__name__']] - return (module, f.f_locals) diff --git a/contrib/python/ipython/py3/IPython/utils/generics.py b/contrib/python/ipython/py3/IPython/utils/generics.py deleted file mode 100644 index 3626ca4cc7..0000000000 --- a/contrib/python/ipython/py3/IPython/utils/generics.py +++ /dev/null @@ -1,29 +0,0 @@ -# encoding: utf-8 -"""Generic functions for extending IPython. -""" - -from IPython.core.error import TryNext -from functools import singledispatch - - -@singledispatch -def inspect_object(obj): - """Called when you do obj?""" - raise TryNext - - -@singledispatch -def complete_object(obj, prev_completions): - """Custom completer dispatching for python objects. - - Parameters - ---------- - obj : object - The object to complete. - prev_completions : list - List of attributes discovered so far. - This should return the list of attributes in obj. If you only wish to - add to the attributes already discovered normally, return - own_attrs + prev_completions. - """ - raise TryNext diff --git a/contrib/python/ipython/py3/IPython/utils/importstring.py b/contrib/python/ipython/py3/IPython/utils/importstring.py deleted file mode 100644 index 51bfc7b569..0000000000 --- a/contrib/python/ipython/py3/IPython/utils/importstring.py +++ /dev/null @@ -1,39 +0,0 @@ -# encoding: utf-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. - - -def import_item(name): - """Import and return ``bar`` given the string ``foo.bar``. - - Calling ``bar = import_item("foo.bar")`` is the functional equivalent of - executing the code ``from foo import bar``. - - Parameters - ---------- - name : string - The fully qualified name of the module/package being imported. - - Returns - ------- - mod : module object - The module that was imported. - """ - - parts = name.rsplit('.', 1) - if len(parts) == 2: - # called with 'foo.bar....' - package, obj = parts - module = __import__(package, fromlist=[obj]) - try: - pak = getattr(module, obj) - except AttributeError as e: - raise ImportError('No module named %s' % obj) from e - return pak - else: - # called with un-dotted string - return __import__(parts[0]) diff --git a/contrib/python/ipython/py3/IPython/utils/io.py b/contrib/python/ipython/py3/IPython/utils/io.py deleted file mode 100644 index 170bc625ac..0000000000 --- a/contrib/python/ipython/py3/IPython/utils/io.py +++ /dev/null @@ -1,157 +0,0 @@ -# encoding: utf-8 -""" -IO related utilities. -""" - -# Copyright (c) IPython Development Team. -# Distributed under the terms of the Modified BSD License. - - - -import atexit -import os -import sys -import tempfile -import warnings -from pathlib import Path -from warnings import warn - -from IPython.utils.decorators import undoc -from .capture import CapturedIO, capture_output - -# setup stdin/stdout/stderr to sys.stdin/sys.stdout/sys.stderr -devnull = open(os.devnull, "w", encoding="utf-8") -atexit.register(devnull.close) - - -class Tee(object): - """A class to duplicate an output stream to stdout/err. - - This works in a manner very similar to the Unix 'tee' command. - - When the object is closed or deleted, it closes the original file given to - it for duplication. - """ - # Inspired by: - # http://mail.python.org/pipermail/python-list/2007-May/442737.html - - def __init__(self, file_or_name, mode="w", channel='stdout'): - """Construct a new Tee object. - - Parameters - ---------- - file_or_name : filename or open filehandle (writable) - File that will be duplicated - mode : optional, valid mode for open(). - If a filename was give, open with this mode. - channel : str, one of ['stdout', 'stderr'] - """ - if channel not in ['stdout', 'stderr']: - raise ValueError('Invalid channel spec %s' % channel) - - if hasattr(file_or_name, 'write') and hasattr(file_or_name, 'seek'): - self.file = file_or_name - else: - encoding = None if "b" in mode else "utf-8" - self.file = open(file_or_name, mode, encoding=encoding) - self.channel = channel - self.ostream = getattr(sys, channel) - setattr(sys, channel, self) - self._closed = False - - def close(self): - """Close the file and restore the channel.""" - self.flush() - setattr(sys, self.channel, self.ostream) - self.file.close() - self._closed = True - - def write(self, data): - """Write data to both channels.""" - self.file.write(data) - self.ostream.write(data) - self.ostream.flush() - - def flush(self): - """Flush both channels.""" - self.file.flush() - self.ostream.flush() - - def __del__(self): - if not self._closed: - self.close() - - -def ask_yes_no(prompt, default=None, interrupt=None): - """Asks a question and returns a boolean (y/n) answer. - - If default is given (one of 'y','n'), it is used if the user input is - empty. If interrupt is given (one of 'y','n'), it is used if the user - presses Ctrl-C. Otherwise the question is repeated until an answer is - given. - - An EOF is treated as the default answer. If there is no default, an - exception is raised to prevent infinite loops. - - Valid answers are: y/yes/n/no (match is not case sensitive).""" - - answers = {'y':True,'n':False,'yes':True,'no':False} - ans = None - while ans not in answers.keys(): - try: - ans = input(prompt+' ').lower() - if not ans: # response was an empty string - ans = default - except KeyboardInterrupt: - if interrupt: - ans = interrupt - print("\r") - except EOFError: - if default in answers.keys(): - ans = default - print() - else: - raise - - return answers[ans] - - -def temp_pyfile(src, ext='.py'): - """Make a temporary python file, return filename and filehandle. - - Parameters - ---------- - src : string or list of strings (no need for ending newlines if list) - Source code to be written to the file. - ext : optional, string - Extension for the generated file. - - Returns - ------- - (filename, open filehandle) - It is the caller's responsibility to close the open file and unlink it. - """ - fname = tempfile.mkstemp(ext)[1] - with open(Path(fname), "w", encoding="utf-8") as f: - f.write(src) - f.flush() - return fname - - -@undoc -def raw_print(*args, **kw): - """DEPRECATED: Raw print to sys.__stdout__, otherwise identical interface to print().""" - warn("IPython.utils.io.raw_print has been deprecated since IPython 7.0", DeprecationWarning, stacklevel=2) - - print(*args, sep=kw.get('sep', ' '), end=kw.get('end', '\n'), - file=sys.__stdout__) - sys.__stdout__.flush() - -@undoc -def raw_print_err(*args, **kw): - """DEPRECATED: Raw print to sys.__stderr__, otherwise identical interface to print().""" - warn("IPython.utils.io.raw_print_err has been deprecated since IPython 7.0", DeprecationWarning, stacklevel=2) - - print(*args, sep=kw.get('sep', ' '), end=kw.get('end', '\n'), - file=sys.__stderr__) - sys.__stderr__.flush() diff --git a/contrib/python/ipython/py3/IPython/utils/ipstruct.py b/contrib/python/ipython/py3/IPython/utils/ipstruct.py deleted file mode 100644 index ed112101a3..0000000000 --- a/contrib/python/ipython/py3/IPython/utils/ipstruct.py +++ /dev/null @@ -1,379 +0,0 @@ -# encoding: utf-8 -"""A dict subclass that supports attribute style access. - -Authors: - -* Fernando Perez (original) -* Brian Granger (refactoring to a dict subclass) -""" - -#----------------------------------------------------------------------------- -# Copyright (C) 2008-2011 The IPython Development Team -# -# Distributed under the terms of the BSD License. The full license is in -# the file COPYING, distributed as part of this software. -#----------------------------------------------------------------------------- - -#----------------------------------------------------------------------------- -# Imports -#----------------------------------------------------------------------------- - -__all__ = ['Struct'] - -#----------------------------------------------------------------------------- -# Code -#----------------------------------------------------------------------------- - - -class Struct(dict): - """A dict subclass with attribute style access. - - This dict subclass has a a few extra features: - - * Attribute style access. - * Protection of class members (like keys, items) when using attribute - style access. - * The ability to restrict assignment to only existing keys. - * Intelligent merging. - * Overloaded operators. - """ - _allownew = True - def __init__(self, *args, **kw): - """Initialize with a dictionary, another Struct, or data. - - Parameters - ---------- - *args : dict, Struct - Initialize with one dict or Struct - **kw : dict - Initialize with key, value pairs. - - Examples - -------- - >>> s = Struct(a=10,b=30) - >>> s.a - 10 - >>> s.b - 30 - >>> s2 = Struct(s,c=30) - >>> sorted(s2.keys()) - ['a', 'b', 'c'] - """ - object.__setattr__(self, '_allownew', True) - dict.__init__(self, *args, **kw) - - def __setitem__(self, key, value): - """Set an item with check for allownew. - - Examples - -------- - >>> s = Struct() - >>> s['a'] = 10 - >>> s.allow_new_attr(False) - >>> s['a'] = 10 - >>> s['a'] - 10 - >>> try: - ... s['b'] = 20 - ... except KeyError: - ... print('this is not allowed') - ... - this is not allowed - """ - if not self._allownew and key not in self: - raise KeyError( - "can't create new attribute %s when allow_new_attr(False)" % key) - dict.__setitem__(self, key, value) - - def __setattr__(self, key, value): - """Set an attr with protection of class members. - - This calls :meth:`self.__setitem__` but convert :exc:`KeyError` to - :exc:`AttributeError`. - - Examples - -------- - >>> s = Struct() - >>> s.a = 10 - >>> s.a - 10 - >>> try: - ... s.get = 10 - ... except AttributeError: - ... print("you can't set a class member") - ... - you can't set a class member - """ - # If key is an str it might be a class member or instance var - if isinstance(key, str): - # I can't simply call hasattr here because it calls getattr, which - # calls self.__getattr__, which returns True for keys in - # self._data. But I only want keys in the class and in - # self.__dict__ - if key in self.__dict__ or hasattr(Struct, key): - raise AttributeError( - 'attr %s is a protected member of class Struct.' % key - ) - try: - self.__setitem__(key, value) - except KeyError as e: - raise AttributeError(e) from e - - def __getattr__(self, key): - """Get an attr by calling :meth:`dict.__getitem__`. - - Like :meth:`__setattr__`, this method converts :exc:`KeyError` to - :exc:`AttributeError`. - - Examples - -------- - >>> s = Struct(a=10) - >>> s.a - 10 - >>> type(s.get) - <...method'> - >>> try: - ... s.b - ... except AttributeError: - ... print("I don't have that key") - ... - I don't have that key - """ - try: - result = self[key] - except KeyError as e: - raise AttributeError(key) from e - else: - return result - - def __iadd__(self, other): - """s += s2 is a shorthand for s.merge(s2). - - Examples - -------- - >>> s = Struct(a=10,b=30) - >>> s2 = Struct(a=20,c=40) - >>> s += s2 - >>> sorted(s.keys()) - ['a', 'b', 'c'] - """ - self.merge(other) - return self - - def __add__(self,other): - """s + s2 -> New Struct made from s.merge(s2). - - Examples - -------- - >>> s1 = Struct(a=10,b=30) - >>> s2 = Struct(a=20,c=40) - >>> s = s1 + s2 - >>> sorted(s.keys()) - ['a', 'b', 'c'] - """ - sout = self.copy() - sout.merge(other) - return sout - - def __sub__(self,other): - """s1 - s2 -> remove keys in s2 from s1. - - Examples - -------- - >>> s1 = Struct(a=10,b=30) - >>> s2 = Struct(a=40) - >>> s = s1 - s2 - >>> s - {'b': 30} - """ - sout = self.copy() - sout -= other - return sout - - def __isub__(self,other): - """Inplace remove keys from self that are in other. - - Examples - -------- - >>> s1 = Struct(a=10,b=30) - >>> s2 = Struct(a=40) - >>> s1 -= s2 - >>> s1 - {'b': 30} - """ - for k in other.keys(): - if k in self: - del self[k] - return self - - def __dict_invert(self, data): - """Helper function for merge. - - Takes a dictionary whose values are lists and returns a dict with - the elements of each list as keys and the original keys as values. - """ - outdict = {} - for k,lst in data.items(): - if isinstance(lst, str): - lst = lst.split() - for entry in lst: - outdict[entry] = k - return outdict - - def dict(self): - return self - - def copy(self): - """Return a copy as a Struct. - - Examples - -------- - >>> s = Struct(a=10,b=30) - >>> s2 = s.copy() - >>> type(s2) is Struct - True - """ - return Struct(dict.copy(self)) - - def hasattr(self, key): - """hasattr function available as a method. - - Implemented like has_key. - - Examples - -------- - >>> s = Struct(a=10) - >>> s.hasattr('a') - True - >>> s.hasattr('b') - False - >>> s.hasattr('get') - False - """ - return key in self - - def allow_new_attr(self, allow = True): - """Set whether new attributes can be created in this Struct. - - This can be used to catch typos by verifying that the attribute user - tries to change already exists in this Struct. - """ - object.__setattr__(self, '_allownew', allow) - - def merge(self, __loc_data__=None, __conflict_solve=None, **kw): - """Merge two Structs with customizable conflict resolution. - - This is similar to :meth:`update`, but much more flexible. First, a - dict is made from data+key=value pairs. When merging this dict with - the Struct S, the optional dictionary 'conflict' is used to decide - what to do. - - If conflict is not given, the default behavior is to preserve any keys - with their current value (the opposite of the :meth:`update` method's - behavior). - - Parameters - ---------- - __loc_data__ : dict, Struct - The data to merge into self - __conflict_solve : dict - The conflict policy dict. The keys are binary functions used to - resolve the conflict and the values are lists of strings naming - the keys the conflict resolution function applies to. Instead of - a list of strings a space separated string can be used, like - 'a b c'. - **kw : dict - Additional key, value pairs to merge in - - Notes - ----- - The `__conflict_solve` dict is a dictionary of binary functions which will be used to - solve key conflicts. Here is an example:: - - __conflict_solve = dict( - func1=['a','b','c'], - func2=['d','e'] - ) - - In this case, the function :func:`func1` will be used to resolve - keys 'a', 'b' and 'c' and the function :func:`func2` will be used for - keys 'd' and 'e'. This could also be written as:: - - __conflict_solve = dict(func1='a b c',func2='d e') - - These functions will be called for each key they apply to with the - form:: - - func1(self['a'], other['a']) - - The return value is used as the final merged value. - - As a convenience, merge() provides five (the most commonly needed) - pre-defined policies: preserve, update, add, add_flip and add_s. The - easiest explanation is their implementation:: - - preserve = lambda old,new: old - update = lambda old,new: new - add = lambda old,new: old + new - add_flip = lambda old,new: new + old # note change of order! - add_s = lambda old,new: old + ' ' + new # only for str! - - You can use those four words (as strings) as keys instead - of defining them as functions, and the merge method will substitute - the appropriate functions for you. - - For more complicated conflict resolution policies, you still need to - construct your own functions. - - Examples - -------- - This show the default policy: - - >>> s = Struct(a=10,b=30) - >>> s2 = Struct(a=20,c=40) - >>> s.merge(s2) - >>> sorted(s.items()) - [('a', 10), ('b', 30), ('c', 40)] - - Now, show how to specify a conflict dict: - - >>> s = Struct(a=10,b=30) - >>> s2 = Struct(a=20,b=40) - >>> conflict = {'update':'a','add':'b'} - >>> s.merge(s2,conflict) - >>> sorted(s.items()) - [('a', 20), ('b', 70)] - """ - - data_dict = dict(__loc_data__,**kw) - - # policies for conflict resolution: two argument functions which return - # the value that will go in the new struct - preserve = lambda old,new: old - update = lambda old,new: new - add = lambda old,new: old + new - add_flip = lambda old,new: new + old # note change of order! - add_s = lambda old,new: old + ' ' + new - - # default policy is to keep current keys when there's a conflict - conflict_solve = dict.fromkeys(self, preserve) - - # the conflict_solve dictionary is given by the user 'inverted': we - # need a name-function mapping, it comes as a function -> names - # dict. Make a local copy (b/c we'll make changes), replace user - # strings for the three builtin policies and invert it. - if __conflict_solve: - inv_conflict_solve_user = __conflict_solve.copy() - for name, func in [('preserve',preserve), ('update',update), - ('add',add), ('add_flip',add_flip), - ('add_s',add_s)]: - if name in inv_conflict_solve_user.keys(): - inv_conflict_solve_user[func] = inv_conflict_solve_user[name] - del inv_conflict_solve_user[name] - conflict_solve.update(self.__dict_invert(inv_conflict_solve_user)) - for key in data_dict: - if key not in self: - self[key] = data_dict[key] - else: - self[key] = conflict_solve[key](self[key],data_dict[key]) - diff --git a/contrib/python/ipython/py3/IPython/utils/jsonutil.py b/contrib/python/ipython/py3/IPython/utils/jsonutil.py deleted file mode 100644 index 2672e09e16..0000000000 --- a/contrib/python/ipython/py3/IPython/utils/jsonutil.py +++ /dev/null @@ -1,5 +0,0 @@ -from warnings import warn - -warn("IPython.utils.jsonutil has moved to jupyter_client.jsonutil", stacklevel=2) - -from jupyter_client.jsonutil import * diff --git a/contrib/python/ipython/py3/IPython/utils/localinterfaces.py b/contrib/python/ipython/py3/IPython/utils/localinterfaces.py deleted file mode 100644 index 2f911222d8..0000000000 --- a/contrib/python/ipython/py3/IPython/utils/localinterfaces.py +++ /dev/null @@ -1,5 +0,0 @@ -from warnings import warn - -warn("IPython.utils.localinterfaces has moved to jupyter_client.localinterfaces", stacklevel=2) - -from jupyter_client.localinterfaces import * diff --git a/contrib/python/ipython/py3/IPython/utils/log.py b/contrib/python/ipython/py3/IPython/utils/log.py deleted file mode 100644 index bb262eda93..0000000000 --- a/contrib/python/ipython/py3/IPython/utils/log.py +++ /dev/null @@ -1,6 +0,0 @@ - -from warnings import warn - -warn("IPython.utils.log has moved to traitlets.log", stacklevel=2) - -from traitlets.log import * diff --git a/contrib/python/ipython/py3/IPython/utils/module_paths.py b/contrib/python/ipython/py3/IPython/utils/module_paths.py deleted file mode 100644 index f9f7cacc33..0000000000 --- a/contrib/python/ipython/py3/IPython/utils/module_paths.py +++ /dev/null @@ -1,71 +0,0 @@ -"""Utility functions for finding modules - -Utility functions for finding modules on sys.path. - -""" -#----------------------------------------------------------------------------- -# Copyright (c) 2011, the IPython Development Team. -# -# Distributed under the terms of the Modified BSD License. -# -# The full license is in the file COPYING.txt, distributed with this software. -#----------------------------------------------------------------------------- - -#----------------------------------------------------------------------------- -# Imports -#----------------------------------------------------------------------------- - -# Stdlib imports -import importlib -import os -import sys - -# Third-party imports - -# Our own imports - - -#----------------------------------------------------------------------------- -# Globals and constants -#----------------------------------------------------------------------------- - -#----------------------------------------------------------------------------- -# Local utilities -#----------------------------------------------------------------------------- - -#----------------------------------------------------------------------------- -# Classes and functions -#----------------------------------------------------------------------------- - -def find_mod(module_name): - """ - Find module `module_name` on sys.path, and return the path to module `module_name`. - - - If `module_name` refers to a module directory, then return path to __init__ file. - - If `module_name` is a directory without an __init__file, return None. - - If module is missing or does not have a `.py` or `.pyw` extension, return None. - - Note that we are not interested in running bytecode. - - Otherwise, return the fill path of the module. - - Parameters - ---------- - module_name : str - - Returns - ------- - module_path : str - Path to module `module_name`, its __init__.py, or None, - depending on above conditions. - """ - spec = importlib.util.find_spec(module_name) - module_path = spec.origin - if module_path is None: - if spec.loader in sys.meta_path: - return spec.loader - return None - else: - split_path = module_path.split(".") - if split_path[-1] in ["py", "pyw"]: - return module_path - else: - return None diff --git a/contrib/python/ipython/py3/IPython/utils/openpy.py b/contrib/python/ipython/py3/IPython/utils/openpy.py deleted file mode 100644 index 297a762c7d..0000000000 --- a/contrib/python/ipython/py3/IPython/utils/openpy.py +++ /dev/null @@ -1,105 +0,0 @@ -""" -Tools to open .py files as Unicode, using the encoding specified within the file, -as per PEP 263. - -Much of the code is taken from the tokenize module in Python 3.2. -""" - -import io -from io import TextIOWrapper, BytesIO -from pathlib import Path -import re -from tokenize import open, detect_encoding - -cookie_re = re.compile(r"coding[:=]\s*([-\w.]+)", re.UNICODE) -cookie_comment_re = re.compile(r"^\s*#.*coding[:=]\s*([-\w.]+)", re.UNICODE) - -def source_to_unicode(txt, errors='replace', skip_encoding_cookie=True): - """Converts a bytes string with python source code to unicode. - - Unicode strings are passed through unchanged. Byte strings are checked - for the python source file encoding cookie to determine encoding. - txt can be either a bytes buffer or a string containing the source - code. - """ - if isinstance(txt, str): - return txt - if isinstance(txt, bytes): - buffer = BytesIO(txt) - else: - buffer = txt - try: - encoding, _ = detect_encoding(buffer.readline) - except SyntaxError: - encoding = "ascii" - buffer.seek(0) - with TextIOWrapper(buffer, encoding, errors=errors, line_buffering=True) as text: - text.mode = 'r' - if skip_encoding_cookie: - return u"".join(strip_encoding_cookie(text)) - else: - return text.read() - -def strip_encoding_cookie(filelike): - """Generator to pull lines from a text-mode file, skipping the encoding - cookie if it is found in the first two lines. - """ - it = iter(filelike) - try: - first = next(it) - if not cookie_comment_re.match(first): - yield first - second = next(it) - if not cookie_comment_re.match(second): - yield second - except StopIteration: - return - - for line in it: - yield line - -def read_py_file(filename, skip_encoding_cookie=True): - """Read a Python file, using the encoding declared inside the file. - - Parameters - ---------- - filename : str - The path to the file to read. - skip_encoding_cookie : bool - If True (the default), and the encoding declaration is found in the first - two lines, that line will be excluded from the output. - - Returns - ------- - A unicode string containing the contents of the file. - """ - filepath = Path(filename) - with open(filepath) as f: # the open function defined in this module. - if skip_encoding_cookie: - return "".join(strip_encoding_cookie(f)) - else: - return f.read() - -def read_py_url(url, errors='replace', skip_encoding_cookie=True): - """Read a Python file from a URL, using the encoding declared inside the file. - - Parameters - ---------- - url : str - The URL from which to fetch the file. - errors : str - How to handle decoding errors in the file. Options are the same as for - bytes.decode(), but here 'replace' is the default. - skip_encoding_cookie : bool - If True (the default), and the encoding declaration is found in the first - two lines, that line will be excluded from the output. - - Returns - ------- - A unicode string containing the contents of the file. - """ - # Deferred import for faster start - from urllib.request import urlopen - response = urlopen(url) - buffer = io.BytesIO(response.read()) - return source_to_unicode(buffer, errors, skip_encoding_cookie) diff --git a/contrib/python/ipython/py3/IPython/utils/path.py b/contrib/python/ipython/py3/IPython/utils/path.py deleted file mode 100644 index 3db33e4c43..0000000000 --- a/contrib/python/ipython/py3/IPython/utils/path.py +++ /dev/null @@ -1,392 +0,0 @@ -# encoding: utf-8 -""" -Utilities for path handling. -""" - -# Copyright (c) IPython Development Team. -# Distributed under the terms of the Modified BSD License. - -import os -import sys -import errno -import shutil -import random -import glob -from warnings import warn - -from IPython.utils.process import system -from IPython.utils.decorators import undoc - -#----------------------------------------------------------------------------- -# Code -#----------------------------------------------------------------------------- -fs_encoding = sys.getfilesystemencoding() - -def _writable_dir(path): - """Whether `path` is a directory, to which the user has write access.""" - return os.path.isdir(path) and os.access(path, os.W_OK) - -if sys.platform == 'win32': - def _get_long_path_name(path): - """Get a long path name (expand ~) on Windows using ctypes. - - Examples - -------- - - >>> get_long_path_name('c:\\\\docume~1') - 'c:\\\\Documents and Settings' - - """ - try: - import ctypes - except ImportError as e: - raise ImportError('you need to have ctypes installed for this to work') from e - _GetLongPathName = ctypes.windll.kernel32.GetLongPathNameW - _GetLongPathName.argtypes = [ctypes.c_wchar_p, ctypes.c_wchar_p, - ctypes.c_uint ] - - buf = ctypes.create_unicode_buffer(260) - rv = _GetLongPathName(path, buf, 260) - if rv == 0 or rv > 260: - return path - else: - return buf.value -else: - def _get_long_path_name(path): - """Dummy no-op.""" - return path - - - -def get_long_path_name(path): - """Expand a path into its long form. - - On Windows this expands any ~ in the paths. On other platforms, it is - a null operation. - """ - return _get_long_path_name(path) - - -def compress_user(path): - """Reverse of :func:`os.path.expanduser` - """ - home = os.path.expanduser('~') - if path.startswith(home): - path = "~" + path[len(home):] - return path - -def get_py_filename(name): - """Return a valid python filename in the current directory. - - If the given name is not a file, it adds '.py' and searches again. - Raises IOError with an informative message if the file isn't found. - """ - - name = os.path.expanduser(name) - if not os.path.isfile(name) and not name.endswith('.py'): - name += '.py' - if os.path.isfile(name): - return name - else: - raise IOError('File `%r` not found.' % name) - - -def filefind(filename: str, path_dirs=None) -> str: - """Find a file by looking through a sequence of paths. - - This iterates through a sequence of paths looking for a file and returns - the full, absolute path of the first occurrence of the file. If no set of - path dirs is given, the filename is tested as is, after running through - :func:`expandvars` and :func:`expanduser`. Thus a simple call:: - - filefind('myfile.txt') - - will find the file in the current working dir, but:: - - filefind('~/myfile.txt') - - Will find the file in the users home directory. This function does not - automatically try any paths, such as the cwd or the user's home directory. - - Parameters - ---------- - filename : str - The filename to look for. - path_dirs : str, None or sequence of str - The sequence of paths to look for the file in. If None, the filename - need to be absolute or be in the cwd. If a string, the string is - put into a sequence and the searched. If a sequence, walk through - each element and join with ``filename``, calling :func:`expandvars` - and :func:`expanduser` before testing for existence. - - Returns - ------- - path : str - returns absolute path to file. - - Raises - ------ - IOError - """ - - # If paths are quoted, abspath gets confused, strip them... - filename = filename.strip('"').strip("'") - # If the input is an absolute path, just check it exists - if os.path.isabs(filename) and os.path.isfile(filename): - return filename - - if path_dirs is None: - path_dirs = ("",) - elif isinstance(path_dirs, str): - path_dirs = (path_dirs,) - - for path in path_dirs: - if path == '.': path = os.getcwd() - testname = expand_path(os.path.join(path, filename)) - if os.path.isfile(testname): - return os.path.abspath(testname) - - raise IOError("File %r does not exist in any of the search paths: %r" % - (filename, path_dirs) ) - - -class HomeDirError(Exception): - pass - - -def get_home_dir(require_writable=False) -> str: - """Return the 'home' directory, as a unicode string. - - Uses os.path.expanduser('~'), and checks for writability. - - See stdlib docs for how this is determined. - For Python <3.8, $HOME is first priority on *ALL* platforms. - For Python >=3.8 on Windows, %HOME% is no longer considered. - - Parameters - ---------- - require_writable : bool [default: False] - if True: - guarantees the return value is a writable directory, otherwise - raises HomeDirError - if False: - The path is resolved, but it is not guaranteed to exist or be writable. - """ - - homedir = os.path.expanduser('~') - # Next line will make things work even when /home/ is a symlink to - # /usr/home as it is on FreeBSD, for example - homedir = os.path.realpath(homedir) - - if not _writable_dir(homedir) and os.name == 'nt': - # expanduser failed, use the registry to get the 'My Documents' folder. - try: - import winreg as wreg - with wreg.OpenKey( - wreg.HKEY_CURRENT_USER, - r"Software\Microsoft\Windows\CurrentVersion\Explorer\Shell Folders" - ) as key: - homedir = wreg.QueryValueEx(key,'Personal')[0] - except: - pass - - if (not require_writable) or _writable_dir(homedir): - assert isinstance(homedir, str), "Homedir should be unicode not bytes" - return homedir - else: - raise HomeDirError('%s is not a writable dir, ' - 'set $HOME environment variable to override' % homedir) - -def get_xdg_dir(): - """Return the XDG_CONFIG_HOME, if it is defined and exists, else None. - - This is only for non-OS X posix (Linux,Unix,etc.) systems. - """ - - env = os.environ - - if os.name == "posix": - # Linux, Unix, AIX, etc. - # use ~/.config if empty OR not set - xdg = env.get("XDG_CONFIG_HOME", None) or os.path.join(get_home_dir(), '.config') - if xdg and _writable_dir(xdg): - assert isinstance(xdg, str) - return xdg - - return None - - -def get_xdg_cache_dir(): - """Return the XDG_CACHE_HOME, if it is defined and exists, else None. - - This is only for non-OS X posix (Linux,Unix,etc.) systems. - """ - - env = os.environ - - if os.name == "posix": - # Linux, Unix, AIX, etc. - # use ~/.cache if empty OR not set - xdg = env.get("XDG_CACHE_HOME", None) or os.path.join(get_home_dir(), '.cache') - if xdg and _writable_dir(xdg): - assert isinstance(xdg, str) - return xdg - - return None - - -def expand_path(s): - """Expand $VARS and ~names in a string, like a shell - - :Examples: - - In [2]: os.environ['FOO']='test' - - In [3]: expand_path('variable FOO is $FOO') - Out[3]: 'variable FOO is test' - """ - # This is a pretty subtle hack. When expand user is given a UNC path - # on Windows (\\server\share$\%username%), os.path.expandvars, removes - # the $ to get (\\server\share\%username%). I think it considered $ - # alone an empty var. But, we need the $ to remains there (it indicates - # a hidden share). - if os.name=='nt': - s = s.replace('$\\', 'IPYTHON_TEMP') - s = os.path.expandvars(os.path.expanduser(s)) - if os.name=='nt': - s = s.replace('IPYTHON_TEMP', '$\\') - return s - - -def unescape_glob(string): - """Unescape glob pattern in `string`.""" - def unescape(s): - for pattern in '*[]!?': - s = s.replace(r'\{0}'.format(pattern), pattern) - return s - return '\\'.join(map(unescape, string.split('\\\\'))) - - -def shellglob(args): - """ - Do glob expansion for each element in `args` and return a flattened list. - - Unmatched glob pattern will remain as-is in the returned list. - - """ - expanded = [] - # Do not unescape backslash in Windows as it is interpreted as - # path separator: - unescape = unescape_glob if sys.platform != 'win32' else lambda x: x - for a in args: - expanded.extend(glob.glob(a) or [unescape(a)]) - return expanded - - -def target_outdated(target,deps): - """Determine whether a target is out of date. - - target_outdated(target,deps) -> 1/0 - - deps: list of filenames which MUST exist. - target: single filename which may or may not exist. - - If target doesn't exist or is older than any file listed in deps, return - true, otherwise return false. - """ - try: - target_time = os.path.getmtime(target) - except os.error: - return 1 - for dep in deps: - dep_time = os.path.getmtime(dep) - if dep_time > target_time: - #print "For target",target,"Dep failed:",dep # dbg - #print "times (dep,tar):",dep_time,target_time # dbg - return 1 - return 0 - - -def target_update(target,deps,cmd): - """Update a target with a given command given a list of dependencies. - - target_update(target,deps,cmd) -> runs cmd if target is outdated. - - This is just a wrapper around target_outdated() which calls the given - command if target is outdated.""" - - if target_outdated(target,deps): - system(cmd) - - -ENOLINK = 1998 - -def link(src, dst): - """Hard links ``src`` to ``dst``, returning 0 or errno. - - Note that the special errno ``ENOLINK`` will be returned if ``os.link`` isn't - supported by the operating system. - """ - - if not hasattr(os, "link"): - return ENOLINK - link_errno = 0 - try: - os.link(src, dst) - except OSError as e: - link_errno = e.errno - return link_errno - - -def link_or_copy(src, dst): - """Attempts to hardlink ``src`` to ``dst``, copying if the link fails. - - Attempts to maintain the semantics of ``shutil.copy``. - - Because ``os.link`` does not overwrite files, a unique temporary file - will be used if the target already exists, then that file will be moved - into place. - """ - - if os.path.isdir(dst): - dst = os.path.join(dst, os.path.basename(src)) - - link_errno = link(src, dst) - if link_errno == errno.EEXIST: - if os.stat(src).st_ino == os.stat(dst).st_ino: - # dst is already a hard link to the correct file, so we don't need - # to do anything else. If we try to link and rename the file - # anyway, we get duplicate files - see http://bugs.python.org/issue21876 - return - - new_dst = dst + "-temp-%04X" %(random.randint(1, 16**4), ) - try: - link_or_copy(src, new_dst) - except: - try: - os.remove(new_dst) - except OSError: - pass - raise - os.rename(new_dst, dst) - elif link_errno != 0: - # Either link isn't supported, or the filesystem doesn't support - # linking, or 'src' and 'dst' are on different filesystems. - shutil.copy(src, dst) - -def ensure_dir_exists(path, mode=0o755): - """ensure that a directory exists - - If it doesn't exist, try to create it and protect against a race condition - if another process is doing the same. - - The default permissions are 755, which differ from os.makedirs default of 777. - """ - if not os.path.exists(path): - try: - os.makedirs(path, mode=mode) - except OSError as e: - if e.errno != errno.EEXIST: - raise - elif not os.path.isdir(path): - raise IOError("%r exists but is not a directory" % path) diff --git a/contrib/python/ipython/py3/IPython/utils/process.py b/contrib/python/ipython/py3/IPython/utils/process.py deleted file mode 100644 index 489b7c13d0..0000000000 --- a/contrib/python/ipython/py3/IPython/utils/process.py +++ /dev/null @@ -1,69 +0,0 @@ -# encoding: utf-8 -""" -Utilities for working with external processes. -""" - -# Copyright (c) IPython Development Team. -# Distributed under the terms of the Modified BSD License. - - -import os -import shutil -import sys - -if sys.platform == 'win32': - from ._process_win32 import system, getoutput, arg_split, check_pid -elif sys.platform == 'cli': - from ._process_cli import system, getoutput, arg_split, check_pid -else: - from ._process_posix import system, getoutput, arg_split, check_pid - -from ._process_common import getoutputerror, get_output_error_code, process_handler - - -class FindCmdError(Exception): - pass - - -def find_cmd(cmd): - """Find absolute path to executable cmd in a cross platform manner. - - This function tries to determine the full path to a command line program - using `which` on Unix/Linux/OS X and `win32api` on Windows. Most of the - time it will use the version that is first on the users `PATH`. - - Warning, don't use this to find IPython command line programs as there - is a risk you will find the wrong one. Instead find those using the - following code and looking for the application itself:: - - import sys - argv = [sys.executable, '-m', 'IPython'] - - Parameters - ---------- - cmd : str - The command line program to look for. - """ - path = shutil.which(cmd) - if path is None: - raise FindCmdError('command could not be found: %s' % cmd) - return path - - -def abbrev_cwd(): - """ Return abbreviated version of cwd, e.g. d:mydir """ - cwd = os.getcwd().replace('\\','/') - drivepart = '' - tail = cwd - if sys.platform == 'win32': - if len(cwd) < 4: - return cwd - drivepart,tail = os.path.splitdrive(cwd) - - - parts = tail.split('/') - if len(parts) > 2: - tail = '/'.join(parts[-2:]) - - return (drivepart + ( - cwd == '/' and '/' or tail)) diff --git a/contrib/python/ipython/py3/IPython/utils/py3compat.py b/contrib/python/ipython/py3/IPython/utils/py3compat.py deleted file mode 100644 index 34af4c58f4..0000000000 --- a/contrib/python/ipython/py3/IPython/utils/py3compat.py +++ /dev/null @@ -1,67 +0,0 @@ -# coding: utf-8 -"""Compatibility tricks for Python 3. Mainly to do with unicode. - -This file is deprecated and will be removed in a future version. -""" -import platform -import builtins as builtin_mod - -from .encoding import DEFAULT_ENCODING - - -def decode(s, encoding=None): - encoding = encoding or DEFAULT_ENCODING - return s.decode(encoding, "replace") - - -def encode(u, encoding=None): - encoding = encoding or DEFAULT_ENCODING - return u.encode(encoding, "replace") - - -def cast_unicode(s, encoding=None): - if isinstance(s, bytes): - return decode(s, encoding) - return s - - -def safe_unicode(e): - """unicode(e) with various fallbacks. Used for exceptions, which may not be - safe to call unicode() on. - """ - try: - return str(e) - except UnicodeError: - pass - - try: - return repr(e) - except UnicodeError: - pass - - return "Unrecoverably corrupt evalue" - - -# keep reference to builtin_mod because the kernel overrides that value -# to forward requests to a frontend. -def input(prompt=""): - return builtin_mod.input(prompt) - - -def execfile(fname, glob, loc=None, compiler=None): - loc = loc if (loc is not None) else glob - with open(fname, "rb") as f: - compiler = compiler or compile - exec(compiler(f.read(), fname, "exec"), glob, loc) - - -PYPY = platform.python_implementation() == "PyPy" - -# Cython still rely on that as a Dec 28 2019 -# See https://github.com/cython/cython/pull/3291 and -# https://github.com/ipython/ipython/issues/12068 -def no_code(x, encoding=None): - return x - - -unicode_to_str = cast_bytes_py2 = no_code diff --git a/contrib/python/ipython/py3/IPython/utils/sentinel.py b/contrib/python/ipython/py3/IPython/utils/sentinel.py deleted file mode 100644 index dc57a2591c..0000000000 --- a/contrib/python/ipython/py3/IPython/utils/sentinel.py +++ /dev/null @@ -1,17 +0,0 @@ -"""Sentinel class for constants with useful reprs""" - -# Copyright (c) IPython Development Team. -# Distributed under the terms of the Modified BSD License. - -class Sentinel(object): - - def __init__(self, name, module, docstring=None): - self.name = name - self.module = module - if docstring: - self.__doc__ = docstring - - - def __repr__(self): - return str(self.module)+'.'+self.name - diff --git a/contrib/python/ipython/py3/IPython/utils/shimmodule.py b/contrib/python/ipython/py3/IPython/utils/shimmodule.py deleted file mode 100644 index 8af44caa98..0000000000 --- a/contrib/python/ipython/py3/IPython/utils/shimmodule.py +++ /dev/null @@ -1,89 +0,0 @@ -"""A shim module for deprecated imports -""" -# Copyright (c) IPython Development Team. -# Distributed under the terms of the Modified BSD License. - -import importlib.abc -import importlib.util -import sys -import types -from importlib import import_module - -from .importstring import import_item - - -class ShimWarning(Warning): - """A warning to show when a module has moved, and a shim is in its place.""" - - -class ShimImporter(importlib.abc.MetaPathFinder): - """Import hook for a shim. - - This ensures that submodule imports return the real target module, - not a clone that will confuse `is` and `isinstance` checks. - """ - def __init__(self, src, mirror): - self.src = src - self.mirror = mirror - - def _mirror_name(self, fullname): - """get the name of the mirrored module""" - - return self.mirror + fullname[len(self.src) :] - - def find_spec(self, fullname, path, target=None): - if fullname.startswith(self.src + "."): - mirror_name = self._mirror_name(fullname) - return importlib.util.find_spec(mirror_name) - - -class ShimModule(types.ModuleType): - - def __init__(self, *args, **kwargs): - self._mirror = kwargs.pop("mirror") - src = kwargs.pop("src", None) - if src: - kwargs['name'] = src.rsplit('.', 1)[-1] - super(ShimModule, self).__init__(*args, **kwargs) - # add import hook for descendent modules - if src: - sys.meta_path.append( - ShimImporter(src=src, mirror=self._mirror) - ) - - @property - def __path__(self): - return [] - - @property - def __spec__(self): - """Don't produce __spec__ until requested""" - return import_module(self._mirror).__spec__ - - def __dir__(self): - return dir(import_module(self._mirror)) - - @property - def __all__(self): - """Ensure __all__ is always defined""" - mod = import_module(self._mirror) - try: - return mod.__all__ - except AttributeError: - return [name for name in dir(mod) if not name.startswith('_')] - - def __getattr__(self, key): - # Use the equivalent of import_item(name), see below - name = "%s.%s" % (self._mirror, key) - try: - return import_item(name) - except ImportError as e: - raise AttributeError(key) from e - - def __repr__(self): - # repr on a module can be called during error handling; make sure - # it does not fail, even if the import fails - try: - return self.__getattr__("__repr__")() - except AttributeError: - return f"<ShimModule for {self._mirror!r}>" diff --git a/contrib/python/ipython/py3/IPython/utils/signatures.py b/contrib/python/ipython/py3/IPython/utils/signatures.py deleted file mode 100644 index 88d72b185e..0000000000 --- a/contrib/python/ipython/py3/IPython/utils/signatures.py +++ /dev/null @@ -1,12 +0,0 @@ -"""DEPRECATED: Function signature objects for callables. - -Use the standard library version if available, as it is more up to date. -Fallback on backport otherwise. -""" - -import warnings -warnings.warn("{} backport for Python 2 is deprecated in IPython 6, which only supports " - "Python 3. Import directly from standard library `inspect`".format(__name__), - DeprecationWarning, stacklevel=2) - -from inspect import BoundArguments, Parameter, Signature, signature diff --git a/contrib/python/ipython/py3/IPython/utils/strdispatch.py b/contrib/python/ipython/py3/IPython/utils/strdispatch.py deleted file mode 100644 index d6bf510535..0000000000 --- a/contrib/python/ipython/py3/IPython/utils/strdispatch.py +++ /dev/null @@ -1,68 +0,0 @@ -"""String dispatch class to match regexps and dispatch commands. -""" - -# Stdlib imports -import re - -# Our own modules -from IPython.core.hooks import CommandChainDispatcher - -# Code begins -class StrDispatch(object): - """Dispatch (lookup) a set of strings / regexps for match. - - Example: - - >>> dis = StrDispatch() - >>> dis.add_s('hei',34, priority = 4) - >>> dis.add_s('hei',123, priority = 2) - >>> dis.add_re('h.i', 686) - >>> print(list(dis.flat_matches('hei'))) - [123, 34, 686] - """ - - def __init__(self): - self.strs = {} - self.regexs = {} - - def add_s(self, s, obj, priority= 0 ): - """ Adds a target 'string' for dispatching """ - - chain = self.strs.get(s, CommandChainDispatcher()) - chain.add(obj,priority) - self.strs[s] = chain - - def add_re(self, regex, obj, priority= 0 ): - """ Adds a target regexp for dispatching """ - - chain = self.regexs.get(regex, CommandChainDispatcher()) - chain.add(obj,priority) - self.regexs[regex] = chain - - def dispatch(self, key): - """ Get a seq of Commandchain objects that match key """ - if key in self.strs: - yield self.strs[key] - - for r, obj in self.regexs.items(): - if re.match(r, key): - yield obj - else: - #print "nomatch",key # dbg - pass - - def __repr__(self): - return "<Strdispatch %s, %s>" % (self.strs, self.regexs) - - def s_matches(self, key): - if key not in self.strs: - return - for el in self.strs[key]: - yield el[1] - - def flat_matches(self, key): - """ Yield all 'value' targets, without priority """ - for val in self.dispatch(key): - for el in val: - yield el[1] # only value, no priority - return diff --git a/contrib/python/ipython/py3/IPython/utils/sysinfo.py b/contrib/python/ipython/py3/IPython/utils/sysinfo.py deleted file mode 100644 index 857f0cf2d8..0000000000 --- a/contrib/python/ipython/py3/IPython/utils/sysinfo.py +++ /dev/null @@ -1,142 +0,0 @@ -# encoding: utf-8 -""" -Utilities for getting information about IPython and the system it's running in. -""" - -#----------------------------------------------------------------------------- -# Copyright (C) 2008-2011 The IPython Development Team -# -# Distributed under the terms of the BSD License. The full license is in -# the file COPYING, distributed as part of this software. -#----------------------------------------------------------------------------- - -#----------------------------------------------------------------------------- -# Imports -#----------------------------------------------------------------------------- - -import os -import platform -import pprint -import sys -import subprocess - -from IPython.core import release -from IPython.utils import _sysinfo, encoding - -#----------------------------------------------------------------------------- -# Code -#----------------------------------------------------------------------------- - -def pkg_commit_hash(pkg_path): - """Get short form of commit hash given directory `pkg_path` - - We get the commit hash from (in order of preference): - - * IPython.utils._sysinfo.commit - * git output, if we are in a git repository - - If these fail, we return a not-found placeholder tuple - - Parameters - ---------- - pkg_path : str - directory containing package - only used for getting commit from active repo - - Returns - ------- - hash_from : str - Where we got the hash from - description - hash_str : str - short form of hash - """ - # Try and get commit from written commit text file - if _sysinfo.commit: - return "installation", _sysinfo.commit - - # maybe we are in a repository - proc = subprocess.Popen('git rev-parse --short HEAD'.split(' '), - stdout=subprocess.PIPE, - stderr=subprocess.PIPE, - cwd=pkg_path) - repo_commit, _ = proc.communicate() - if repo_commit: - return 'repository', repo_commit.strip().decode('ascii') - return '(none found)', '<not found>' - - -def pkg_info(pkg_path): - """Return dict describing the context of this package - - Parameters - ---------- - pkg_path : str - path containing __init__.py for package - - Returns - ------- - context : dict - with named parameters of interest - """ - src, hsh = pkg_commit_hash(pkg_path) - return dict( - ipython_version=release.version, - ipython_path=pkg_path, - commit_source=src, - commit_hash=hsh, - sys_version=sys.version, - sys_executable=sys.executable, - sys_platform=sys.platform, - platform=platform.platform(), - os_name=os.name, - default_encoding=encoding.DEFAULT_ENCODING, - ) - -def get_sys_info(): - """Return useful information about IPython and the system, as a dict.""" - p = os.path - path = p.realpath(p.dirname(p.abspath(p.join(__file__, '..')))) - return pkg_info(path) - -def sys_info(): - """Return useful information about IPython and the system, as a string. - - Examples - -------- - :: - - In [2]: print(sys_info()) - {'commit_hash': '144fdae', # random - 'commit_source': 'repository', - 'ipython_path': '/home/fperez/usr/lib/python2.6/site-packages/IPython', - 'ipython_version': '0.11.dev', - 'os_name': 'posix', - 'platform': 'Linux-2.6.35-22-generic-i686-with-Ubuntu-10.10-maverick', - 'sys_executable': '/usr/bin/python', - 'sys_platform': 'linux2', - 'sys_version': '2.6.6 (r266:84292, Sep 15 2010, 15:52:39) \\n[GCC 4.4.5]'} - """ - return pprint.pformat(get_sys_info()) - - -def num_cpus(): - """DEPRECATED - - Return the effective number of CPUs in the system as an integer. - - This cross-platform function makes an attempt at finding the total number of - available CPUs in the system, as returned by various underlying system and - python calls. - - If it can't find a sensible answer, it returns 1 (though an error *may* make - it return a large positive number that's actually incorrect). - """ - import warnings - - warnings.warn( - "`num_cpus` is deprecated since IPython 8.0. Use `os.cpu_count` instead.", - DeprecationWarning, - stacklevel=2, - ) - - return os.cpu_count() or 1 diff --git a/contrib/python/ipython/py3/IPython/utils/syspathcontext.py b/contrib/python/ipython/py3/IPython/utils/syspathcontext.py deleted file mode 100644 index 7af1ab60af..0000000000 --- a/contrib/python/ipython/py3/IPython/utils/syspathcontext.py +++ /dev/null @@ -1,71 +0,0 @@ -# encoding: utf-8 -""" -Context managers for adding things to sys.path temporarily. - -Authors: - -* Brian Granger -""" - -#----------------------------------------------------------------------------- -# Copyright (C) 2008-2011 The IPython Development Team -# -# Distributed under the terms of the BSD License. The full license is in -# the file COPYING, distributed as part of this software. -#----------------------------------------------------------------------------- - -import sys -import warnings - - -class appended_to_syspath(object): - """ - Deprecated since IPython 8.1, no replacements. - - A context for appending a directory to sys.path for a second.""" - - def __init__(self, dir): - warnings.warn( - "`appended_to_syspath` is deprecated since IPython 8.1, and has no replacements", - DeprecationWarning, - stacklevel=2, - ) - self.dir = dir - - def __enter__(self): - if self.dir not in sys.path: - sys.path.append(self.dir) - self.added = True - else: - self.added = False - - def __exit__(self, type, value, traceback): - if self.added: - try: - sys.path.remove(self.dir) - except ValueError: - pass - # Returning False causes any exceptions to be re-raised. - return False - -class prepended_to_syspath(object): - """A context for prepending a directory to sys.path for a second.""" - - def __init__(self, dir): - self.dir = dir - - def __enter__(self): - if self.dir not in sys.path: - sys.path.insert(0,self.dir) - self.added = True - else: - self.added = False - - def __exit__(self, type, value, traceback): - if self.added: - try: - sys.path.remove(self.dir) - except ValueError: - pass - # Returning False causes any exceptions to be re-raised. - return False diff --git a/contrib/python/ipython/py3/IPython/utils/tempdir.py b/contrib/python/ipython/py3/IPython/utils/tempdir.py deleted file mode 100644 index 5afc5d6425..0000000000 --- a/contrib/python/ipython/py3/IPython/utils/tempdir.py +++ /dev/null @@ -1,58 +0,0 @@ -""" This module contains classes - NamedFileInTemporaryDirectory, TemporaryWorkingDirectory. - -These classes add extra features such as creating a named file in temporary directory and -creating a context manager for the working directory which is also temporary. -""" - -import os as _os -from pathlib import Path -from tempfile import TemporaryDirectory - - -class NamedFileInTemporaryDirectory(object): - def __init__(self, filename, mode="w+b", bufsize=-1, add_to_syspath=False, **kwds): - """ - Open a file named `filename` in a temporary directory. - - This context manager is preferred over `NamedTemporaryFile` in - stdlib `tempfile` when one needs to reopen the file. - - Arguments `mode` and `bufsize` are passed to `open`. - Rest of the arguments are passed to `TemporaryDirectory`. - - """ - self._tmpdir = TemporaryDirectory(**kwds) - path = Path(self._tmpdir.name) / filename - encoding = None if "b" in mode else "utf-8" - self.file = open(path, mode, bufsize, encoding=encoding) - - def cleanup(self): - self.file.close() - self._tmpdir.cleanup() - - __del__ = cleanup - - def __enter__(self): - return self.file - - def __exit__(self, type, value, traceback): - self.cleanup() - - -class TemporaryWorkingDirectory(TemporaryDirectory): - """ - Creates a temporary directory and sets the cwd to that directory. - Automatically reverts to previous cwd upon cleanup. - Usage example: - - with TemporaryWorkingDirectory() as tmpdir: - ... - """ - def __enter__(self): - self.old_wd = Path.cwd() - _os.chdir(self.name) - return super(TemporaryWorkingDirectory, self).__enter__() - - def __exit__(self, exc, value, tb): - _os.chdir(self.old_wd) - return super(TemporaryWorkingDirectory, self).__exit__(exc, value, tb) diff --git a/contrib/python/ipython/py3/IPython/utils/terminal.py b/contrib/python/ipython/py3/IPython/utils/terminal.py deleted file mode 100644 index 49fd3fe173..0000000000 --- a/contrib/python/ipython/py3/IPython/utils/terminal.py +++ /dev/null @@ -1,129 +0,0 @@ -# encoding: utf-8 -""" -Utilities for working with terminals. - -Authors: - -* Brian E. Granger -* Fernando Perez -* Alexander Belchenko (e-mail: bialix AT ukr.net) -""" - -# Copyright (c) IPython Development Team. -# Distributed under the terms of the Modified BSD License. - -import os -import sys -import warnings -from shutil import get_terminal_size as _get_terminal_size - -# This variable is part of the expected API of the module: -ignore_termtitle = True - - - -if os.name == 'posix': - def _term_clear(): - os.system('clear') -elif sys.platform == 'win32': - def _term_clear(): - os.system('cls') -else: - def _term_clear(): - pass - - - -def toggle_set_term_title(val): - """Control whether set_term_title is active or not. - - set_term_title() allows writing to the console titlebar. In embedded - widgets this can cause problems, so this call can be used to toggle it on - or off as needed. - - The default state of the module is for the function to be disabled. - - Parameters - ---------- - val : bool - If True, set_term_title() actually writes to the terminal (using the - appropriate platform-specific module). If False, it is a no-op. - """ - global ignore_termtitle - ignore_termtitle = not(val) - - -def _set_term_title(*args,**kw): - """Dummy no-op.""" - pass - - -def _restore_term_title(): - pass - - -def _set_term_title_xterm(title): - """ Change virtual terminal title in xterm-workalikes """ - # save the current title to the xterm "stack" - sys.stdout.write('\033[22;0t') - sys.stdout.write('\033]0;%s\007' % title) - - -def _restore_term_title_xterm(): - sys.stdout.write('\033[23;0t') - - -if os.name == 'posix': - TERM = os.environ.get('TERM','') - if TERM.startswith('xterm'): - _set_term_title = _set_term_title_xterm - _restore_term_title = _restore_term_title_xterm -elif sys.platform == 'win32': - try: - import ctypes - - SetConsoleTitleW = ctypes.windll.kernel32.SetConsoleTitleW - SetConsoleTitleW.argtypes = [ctypes.c_wchar_p] - - def _set_term_title(title): - """Set terminal title using ctypes to access the Win32 APIs.""" - SetConsoleTitleW(title) - except ImportError: - def _set_term_title(title): - """Set terminal title using the 'title' command.""" - global ignore_termtitle - - try: - # Cannot be on network share when issuing system commands - curr = os.getcwd() - os.chdir("C:") - ret = os.system("title " + title) - finally: - os.chdir(curr) - if ret: - # non-zero return code signals error, don't try again - ignore_termtitle = True - - -def set_term_title(title): - """Set terminal title using the necessary platform-dependent calls.""" - if ignore_termtitle: - return - _set_term_title(title) - - -def restore_term_title(): - """Restore, if possible, terminal title to the original state""" - if ignore_termtitle: - return - _restore_term_title() - - -def freeze_term_title(): - warnings.warn("This function is deprecated, use toggle_set_term_title()") - global ignore_termtitle - ignore_termtitle = True - - -def get_terminal_size(defaultx=80, defaulty=25): - return _get_terminal_size((defaultx, defaulty)) diff --git a/contrib/python/ipython/py3/IPython/utils/text.py b/contrib/python/ipython/py3/IPython/utils/text.py deleted file mode 100644 index 74bccddf68..0000000000 --- a/contrib/python/ipython/py3/IPython/utils/text.py +++ /dev/null @@ -1,752 +0,0 @@ -# encoding: utf-8 -""" -Utilities for working with strings and text. - -Inheritance diagram: - -.. inheritance-diagram:: IPython.utils.text - :parts: 3 -""" - -import os -import re -import string -import sys -import textwrap -from string import Formatter -from pathlib import Path - - -# datetime.strftime date format for ipython -if sys.platform == 'win32': - date_format = "%B %d, %Y" -else: - date_format = "%B %-d, %Y" - -class LSString(str): - """String derivative with a special access attributes. - - These are normal strings, but with the special attributes: - - .l (or .list) : value as list (split on newlines). - .n (or .nlstr): original value (the string itself). - .s (or .spstr): value as whitespace-separated string. - .p (or .paths): list of path objects (requires path.py package) - - Any values which require transformations are computed only once and - cached. - - Such strings are very useful to efficiently interact with the shell, which - typically only understands whitespace-separated options for commands.""" - - def get_list(self): - try: - return self.__list - except AttributeError: - self.__list = self.split('\n') - return self.__list - - l = list = property(get_list) - - def get_spstr(self): - try: - return self.__spstr - except AttributeError: - self.__spstr = self.replace('\n',' ') - return self.__spstr - - s = spstr = property(get_spstr) - - def get_nlstr(self): - return self - - n = nlstr = property(get_nlstr) - - def get_paths(self): - try: - return self.__paths - except AttributeError: - self.__paths = [Path(p) for p in self.split('\n') if os.path.exists(p)] - return self.__paths - - p = paths = property(get_paths) - -# FIXME: We need to reimplement type specific displayhook and then add this -# back as a custom printer. This should also be moved outside utils into the -# core. - -# def print_lsstring(arg): -# """ Prettier (non-repr-like) and more informative printer for LSString """ -# print "LSString (.p, .n, .l, .s available). Value:" -# print arg -# -# -# print_lsstring = result_display.register(LSString)(print_lsstring) - - -class SList(list): - """List derivative with a special access attributes. - - These are normal lists, but with the special attributes: - - * .l (or .list) : value as list (the list itself). - * .n (or .nlstr): value as a string, joined on newlines. - * .s (or .spstr): value as a string, joined on spaces. - * .p (or .paths): list of path objects (requires path.py package) - - Any values which require transformations are computed only once and - cached.""" - - def get_list(self): - return self - - l = list = property(get_list) - - def get_spstr(self): - try: - return self.__spstr - except AttributeError: - self.__spstr = ' '.join(self) - return self.__spstr - - s = spstr = property(get_spstr) - - def get_nlstr(self): - try: - return self.__nlstr - except AttributeError: - self.__nlstr = '\n'.join(self) - return self.__nlstr - - n = nlstr = property(get_nlstr) - - def get_paths(self): - try: - return self.__paths - except AttributeError: - self.__paths = [Path(p) for p in self if os.path.exists(p)] - return self.__paths - - p = paths = property(get_paths) - - def grep(self, pattern, prune = False, field = None): - """ Return all strings matching 'pattern' (a regex or callable) - - This is case-insensitive. If prune is true, return all items - NOT matching the pattern. - - If field is specified, the match must occur in the specified - whitespace-separated field. - - Examples:: - - a.grep( lambda x: x.startswith('C') ) - a.grep('Cha.*log', prune=1) - a.grep('chm', field=-1) - """ - - def match_target(s): - if field is None: - return s - parts = s.split() - try: - tgt = parts[field] - return tgt - except IndexError: - return "" - - if isinstance(pattern, str): - pred = lambda x : re.search(pattern, x, re.IGNORECASE) - else: - pred = pattern - if not prune: - return SList([el for el in self if pred(match_target(el))]) - else: - return SList([el for el in self if not pred(match_target(el))]) - - def fields(self, *fields): - """ Collect whitespace-separated fields from string list - - Allows quick awk-like usage of string lists. - - Example data (in var a, created by 'a = !ls -l'):: - - -rwxrwxrwx 1 ville None 18 Dec 14 2006 ChangeLog - drwxrwxrwx+ 6 ville None 0 Oct 24 18:05 IPython - - * ``a.fields(0)`` is ``['-rwxrwxrwx', 'drwxrwxrwx+']`` - * ``a.fields(1,0)`` is ``['1 -rwxrwxrwx', '6 drwxrwxrwx+']`` - (note the joining by space). - * ``a.fields(-1)`` is ``['ChangeLog', 'IPython']`` - - IndexErrors are ignored. - - Without args, fields() just split()'s the strings. - """ - if len(fields) == 0: - return [el.split() for el in self] - - res = SList() - for el in [f.split() for f in self]: - lineparts = [] - - for fd in fields: - try: - lineparts.append(el[fd]) - except IndexError: - pass - if lineparts: - res.append(" ".join(lineparts)) - - return res - - def sort(self,field= None, nums = False): - """ sort by specified fields (see fields()) - - Example:: - - a.sort(1, nums = True) - - Sorts a by second field, in numerical order (so that 21 > 3) - - """ - - #decorate, sort, undecorate - if field is not None: - dsu = [[SList([line]).fields(field), line] for line in self] - else: - dsu = [[line, line] for line in self] - if nums: - for i in range(len(dsu)): - numstr = "".join([ch for ch in dsu[i][0] if ch.isdigit()]) - try: - n = int(numstr) - except ValueError: - n = 0 - dsu[i][0] = n - - - dsu.sort() - return SList([t[1] for t in dsu]) - - -# FIXME: We need to reimplement type specific displayhook and then add this -# back as a custom printer. This should also be moved outside utils into the -# core. - -# def print_slist(arg): -# """ Prettier (non-repr-like) and more informative printer for SList """ -# print "SList (.p, .n, .l, .s, .grep(), .fields(), sort() available):" -# if hasattr(arg, 'hideonce') and arg.hideonce: -# arg.hideonce = False -# return -# -# nlprint(arg) # This was a nested list printer, now removed. -# -# print_slist = result_display.register(SList)(print_slist) - - -def indent(instr,nspaces=4, ntabs=0, flatten=False): - """Indent a string a given number of spaces or tabstops. - - indent(str,nspaces=4,ntabs=0) -> indent str by ntabs+nspaces. - - Parameters - ---------- - instr : basestring - The string to be indented. - nspaces : int (default: 4) - The number of spaces to be indented. - ntabs : int (default: 0) - The number of tabs to be indented. - flatten : bool (default: False) - Whether to scrub existing indentation. If True, all lines will be - aligned to the same indentation. If False, existing indentation will - be strictly increased. - - Returns - ------- - str|unicode : string indented by ntabs and nspaces. - - """ - if instr is None: - return - ind = '\t'*ntabs+' '*nspaces - if flatten: - pat = re.compile(r'^\s*', re.MULTILINE) - else: - pat = re.compile(r'^', re.MULTILINE) - outstr = re.sub(pat, ind, instr) - if outstr.endswith(os.linesep+ind): - return outstr[:-len(ind)] - else: - return outstr - - -def list_strings(arg): - """Always return a list of strings, given a string or list of strings - as input. - - Examples - -------- - :: - - In [7]: list_strings('A single string') - Out[7]: ['A single string'] - - In [8]: list_strings(['A single string in a list']) - Out[8]: ['A single string in a list'] - - In [9]: list_strings(['A','list','of','strings']) - Out[9]: ['A', 'list', 'of', 'strings'] - """ - - if isinstance(arg, str): - return [arg] - else: - return arg - - -def marquee(txt='',width=78,mark='*'): - """Return the input string centered in a 'marquee'. - - Examples - -------- - :: - - In [16]: marquee('A test',40) - Out[16]: '**************** A test ****************' - - In [17]: marquee('A test',40,'-') - Out[17]: '---------------- A test ----------------' - - In [18]: marquee('A test',40,' ') - Out[18]: ' A test ' - - """ - if not txt: - return (mark*width)[:width] - nmark = (width-len(txt)-2)//len(mark)//2 - if nmark < 0: nmark =0 - marks = mark*nmark - return '%s %s %s' % (marks,txt,marks) - - -ini_spaces_re = re.compile(r'^(\s+)') - -def num_ini_spaces(strng): - """Return the number of initial spaces in a string""" - - ini_spaces = ini_spaces_re.match(strng) - if ini_spaces: - return ini_spaces.end() - else: - return 0 - - -def format_screen(strng): - """Format a string for screen printing. - - This removes some latex-type format codes.""" - # Paragraph continue - par_re = re.compile(r'\\$',re.MULTILINE) - strng = par_re.sub('',strng) - return strng - - -def dedent(text): - """Equivalent of textwrap.dedent that ignores unindented first line. - - This means it will still dedent strings like: - '''foo - is a bar - ''' - - For use in wrap_paragraphs. - """ - - if text.startswith('\n'): - # text starts with blank line, don't ignore the first line - return textwrap.dedent(text) - - # split first line - splits = text.split('\n',1) - if len(splits) == 1: - # only one line - return textwrap.dedent(text) - - first, rest = splits - # dedent everything but the first line - rest = textwrap.dedent(rest) - return '\n'.join([first, rest]) - - -def wrap_paragraphs(text, ncols=80): - """Wrap multiple paragraphs to fit a specified width. - - This is equivalent to textwrap.wrap, but with support for multiple - paragraphs, as separated by empty lines. - - Returns - ------- - list of complete paragraphs, wrapped to fill `ncols` columns. - """ - paragraph_re = re.compile(r'\n(\s*\n)+', re.MULTILINE) - text = dedent(text).strip() - paragraphs = paragraph_re.split(text)[::2] # every other entry is space - out_ps = [] - indent_re = re.compile(r'\n\s+', re.MULTILINE) - for p in paragraphs: - # presume indentation that survives dedent is meaningful formatting, - # so don't fill unless text is flush. - if indent_re.search(p) is None: - # wrap paragraph - p = textwrap.fill(p, ncols) - out_ps.append(p) - return out_ps - - -def strip_email_quotes(text): - """Strip leading email quotation characters ('>'). - - Removes any combination of leading '>' interspersed with whitespace that - appears *identically* in all lines of the input text. - - Parameters - ---------- - text : str - - Examples - -------- - - Simple uses:: - - In [2]: strip_email_quotes('> > text') - Out[2]: 'text' - - In [3]: strip_email_quotes('> > text\\n> > more') - Out[3]: 'text\\nmore' - - Note how only the common prefix that appears in all lines is stripped:: - - In [4]: strip_email_quotes('> > text\\n> > more\\n> more...') - Out[4]: '> text\\n> more\\nmore...' - - So if any line has no quote marks ('>'), then none are stripped from any - of them :: - - In [5]: strip_email_quotes('> > text\\n> > more\\nlast different') - Out[5]: '> > text\\n> > more\\nlast different' - """ - lines = text.splitlines() - strip_len = 0 - - for characters in zip(*lines): - # Check if all characters in this position are the same - if len(set(characters)) > 1: - break - prefix_char = characters[0] - - if prefix_char in string.whitespace or prefix_char == ">": - strip_len += 1 - else: - break - - text = "\n".join([ln[strip_len:] for ln in lines]) - return text - - -def strip_ansi(source): - """ - Remove ansi escape codes from text. - - Parameters - ---------- - source : str - Source to remove the ansi from - """ - return re.sub(r'\033\[(\d|;)+?m', '', source) - - -class EvalFormatter(Formatter): - """A String Formatter that allows evaluation of simple expressions. - - Note that this version interprets a `:` as specifying a format string (as per - standard string formatting), so if slicing is required, you must explicitly - create a slice. - - This is to be used in templating cases, such as the parallel batch - script templates, where simple arithmetic on arguments is useful. - - Examples - -------- - :: - - In [1]: f = EvalFormatter() - In [2]: f.format('{n//4}', n=8) - Out[2]: '2' - - In [3]: f.format("{greeting[slice(2,4)]}", greeting="Hello") - Out[3]: 'll' - """ - def get_field(self, name, args, kwargs): - v = eval(name, kwargs) - return v, name - -#XXX: As of Python 3.4, the format string parsing no longer splits on a colon -# inside [], so EvalFormatter can handle slicing. Once we only support 3.4 and -# above, it should be possible to remove FullEvalFormatter. - -class FullEvalFormatter(Formatter): - """A String Formatter that allows evaluation of simple expressions. - - Any time a format key is not found in the kwargs, - it will be tried as an expression in the kwargs namespace. - - Note that this version allows slicing using [1:2], so you cannot specify - a format string. Use :class:`EvalFormatter` to permit format strings. - - Examples - -------- - :: - - In [1]: f = FullEvalFormatter() - In [2]: f.format('{n//4}', n=8) - Out[2]: '2' - - In [3]: f.format('{list(range(5))[2:4]}') - Out[3]: '[2, 3]' - - In [4]: f.format('{3*2}') - Out[4]: '6' - """ - # copied from Formatter._vformat with minor changes to allow eval - # and replace the format_spec code with slicing - def vformat(self, format_string:str, args, kwargs)->str: - result = [] - for literal_text, field_name, format_spec, conversion in \ - self.parse(format_string): - - # output the literal text - if literal_text: - result.append(literal_text) - - # if there's a field, output it - if field_name is not None: - # this is some markup, find the object and do - # the formatting - - if format_spec: - # override format spec, to allow slicing: - field_name = ':'.join([field_name, format_spec]) - - # eval the contents of the field for the object - # to be formatted - obj = eval(field_name, kwargs) - - # do any conversion on the resulting object - obj = self.convert_field(obj, conversion) - - # format the object and append to the result - result.append(self.format_field(obj, '')) - - return ''.join(result) - - -class DollarFormatter(FullEvalFormatter): - """Formatter allowing Itpl style $foo replacement, for names and attribute - access only. Standard {foo} replacement also works, and allows full - evaluation of its arguments. - - Examples - -------- - :: - - In [1]: f = DollarFormatter() - In [2]: f.format('{n//4}', n=8) - Out[2]: '2' - - In [3]: f.format('23 * 76 is $result', result=23*76) - Out[3]: '23 * 76 is 1748' - - In [4]: f.format('$a or {b}', a=1, b=2) - Out[4]: '1 or 2' - """ - _dollar_pattern_ignore_single_quote = re.compile(r"(.*?)\$(\$?[\w\.]+)(?=([^']*'[^']*')*[^']*$)") - def parse(self, fmt_string): - for literal_txt, field_name, format_spec, conversion \ - in Formatter.parse(self, fmt_string): - - # Find $foo patterns in the literal text. - continue_from = 0 - txt = "" - for m in self._dollar_pattern_ignore_single_quote.finditer(literal_txt): - new_txt, new_field = m.group(1,2) - # $$foo --> $foo - if new_field.startswith("$"): - txt += new_txt + new_field - else: - yield (txt + new_txt, new_field, "", None) - txt = "" - continue_from = m.end() - - # Re-yield the {foo} style pattern - yield (txt + literal_txt[continue_from:], field_name, format_spec, conversion) - - def __repr__(self): - return "<DollarFormatter>" - -#----------------------------------------------------------------------------- -# Utils to columnize a list of string -#----------------------------------------------------------------------------- - -def _col_chunks(l, max_rows, row_first=False): - """Yield successive max_rows-sized column chunks from l.""" - if row_first: - ncols = (len(l) // max_rows) + (len(l) % max_rows > 0) - for i in range(ncols): - yield [l[j] for j in range(i, len(l), ncols)] - else: - for i in range(0, len(l), max_rows): - yield l[i:(i + max_rows)] - - -def _find_optimal(rlist, row_first=False, separator_size=2, displaywidth=80): - """Calculate optimal info to columnize a list of string""" - for max_rows in range(1, len(rlist) + 1): - col_widths = list(map(max, _col_chunks(rlist, max_rows, row_first))) - sumlength = sum(col_widths) - ncols = len(col_widths) - if sumlength + separator_size * (ncols - 1) <= displaywidth: - break - return {'num_columns': ncols, - 'optimal_separator_width': (displaywidth - sumlength) // (ncols - 1) if (ncols - 1) else 0, - 'max_rows': max_rows, - 'column_widths': col_widths - } - - -def _get_or_default(mylist, i, default=None): - """return list item number, or default if don't exist""" - if i >= len(mylist): - return default - else : - return mylist[i] - - -def compute_item_matrix(items, row_first=False, empty=None, *args, **kwargs) : - """Returns a nested list, and info to columnize items - - Parameters - ---------- - items - list of strings to columize - row_first : (default False) - Whether to compute columns for a row-first matrix instead of - column-first (default). - empty : (default None) - default value to fill list if needed - separator_size : int (default=2) - How much characters will be used as a separation between each columns. - displaywidth : int (default=80) - The width of the area onto which the columns should enter - - Returns - ------- - strings_matrix - nested list of string, the outer most list contains as many list as - rows, the innermost lists have each as many element as columns. If the - total number of elements in `items` does not equal the product of - rows*columns, the last element of some lists are filled with `None`. - dict_info - some info to make columnize easier: - - num_columns - number of columns - max_rows - maximum number of rows (final number may be less) - column_widths - list of with of each columns - optimal_separator_width - best separator width between columns - - Examples - -------- - :: - - In [1]: l = ['aaa','b','cc','d','eeeee','f','g','h','i','j','k','l'] - In [2]: list, info = compute_item_matrix(l, displaywidth=12) - In [3]: list - Out[3]: [['aaa', 'f', 'k'], ['b', 'g', 'l'], ['cc', 'h', None], ['d', 'i', None], ['eeeee', 'j', None]] - In [4]: ideal = {'num_columns': 3, 'column_widths': [5, 1, 1], 'optimal_separator_width': 2, 'max_rows': 5} - In [5]: all((info[k] == ideal[k] for k in ideal.keys())) - Out[5]: True - """ - info = _find_optimal(list(map(len, items)), row_first, *args, **kwargs) - nrow, ncol = info['max_rows'], info['num_columns'] - if row_first: - return ([[_get_or_default(items, r * ncol + c, default=empty) for c in range(ncol)] for r in range(nrow)], info) - else: - return ([[_get_or_default(items, c * nrow + r, default=empty) for c in range(ncol)] for r in range(nrow)], info) - - -def columnize(items, row_first=False, separator=" ", displaywidth=80, spread=False): - """Transform a list of strings into a single string with columns. - - Parameters - ---------- - items : sequence of strings - The strings to process. - row_first : (default False) - Whether to compute columns for a row-first matrix instead of - column-first (default). - separator : str, optional [default is two spaces] - The string that separates columns. - displaywidth : int, optional [default is 80] - Width of the display in number of characters. - - Returns - ------- - The formatted string. - """ - if not items: - return '\n' - matrix, info = compute_item_matrix(items, row_first=row_first, separator_size=len(separator), displaywidth=displaywidth) - if spread: - separator = separator.ljust(int(info['optimal_separator_width'])) - fmatrix = [filter(None, x) for x in matrix] - sjoin = lambda x : separator.join([ y.ljust(w, ' ') for y, w in zip(x, info['column_widths'])]) - return '\n'.join(map(sjoin, fmatrix))+'\n' - - -def get_text_list(list_, last_sep=' and ', sep=", ", wrap_item_with=""): - """ - Return a string with a natural enumeration of items - - >>> get_text_list(['a', 'b', 'c', 'd']) - 'a, b, c and d' - >>> get_text_list(['a', 'b', 'c'], ' or ') - 'a, b or c' - >>> get_text_list(['a', 'b', 'c'], ', ') - 'a, b, c' - >>> get_text_list(['a', 'b'], ' or ') - 'a or b' - >>> get_text_list(['a']) - 'a' - >>> get_text_list([]) - '' - >>> get_text_list(['a', 'b'], wrap_item_with="`") - '`a` and `b`' - >>> get_text_list(['a', 'b', 'c', 'd'], " = ", sep=" + ") - 'a + b + c = d' - """ - if len(list_) == 0: - return '' - if wrap_item_with: - list_ = ['%s%s%s' % (wrap_item_with, item, wrap_item_with) for - item in list_] - if len(list_) == 1: - return list_[0] - return '%s%s%s' % ( - sep.join(i for i in list_[:-1]), - last_sep, list_[-1]) diff --git a/contrib/python/ipython/py3/IPython/utils/timing.py b/contrib/python/ipython/py3/IPython/utils/timing.py deleted file mode 100644 index 3a181ae728..0000000000 --- a/contrib/python/ipython/py3/IPython/utils/timing.py +++ /dev/null @@ -1,123 +0,0 @@ -# encoding: utf-8 -""" -Utilities for timing code execution. -""" - -#----------------------------------------------------------------------------- -# Copyright (C) 2008-2011 The IPython Development Team -# -# Distributed under the terms of the BSD License. The full license is in -# the file COPYING, distributed as part of this software. -#----------------------------------------------------------------------------- - -#----------------------------------------------------------------------------- -# Imports -#----------------------------------------------------------------------------- - -import time - -#----------------------------------------------------------------------------- -# Code -#----------------------------------------------------------------------------- - -# If possible (Unix), use the resource module instead of time.clock() -try: - import resource -except ImportError: - resource = None - -# Some implementations (like jyputerlite) don't have getrusage -if resource is not None and hasattr(resource, "getrusage"): - def clocku(): - """clocku() -> floating point number - - Return the *USER* CPU time in seconds since the start of the process. - This is done via a call to resource.getrusage, so it avoids the - wraparound problems in time.clock().""" - - return resource.getrusage(resource.RUSAGE_SELF)[0] - - def clocks(): - """clocks() -> floating point number - - Return the *SYSTEM* CPU time in seconds since the start of the process. - This is done via a call to resource.getrusage, so it avoids the - wraparound problems in time.clock().""" - - return resource.getrusage(resource.RUSAGE_SELF)[1] - - def clock(): - """clock() -> floating point number - - Return the *TOTAL USER+SYSTEM* CPU time in seconds since the start of - the process. This is done via a call to resource.getrusage, so it - avoids the wraparound problems in time.clock().""" - - u,s = resource.getrusage(resource.RUSAGE_SELF)[:2] - return u+s - - def clock2(): - """clock2() -> (t_user,t_system) - - Similar to clock(), but return a tuple of user/system times.""" - return resource.getrusage(resource.RUSAGE_SELF)[:2] - -else: - # There is no distinction of user/system time under windows, so we just use - # time.process_time() for everything... - clocku = clocks = clock = time.process_time - - def clock2(): - """Under windows, system CPU time can't be measured. - - This just returns process_time() and zero.""" - return time.process_time(), 0.0 - - -def timings_out(reps,func,*args,**kw): - """timings_out(reps,func,*args,**kw) -> (t_total,t_per_call,output) - - Execute a function reps times, return a tuple with the elapsed total - CPU time in seconds, the time per call and the function's output. - - Under Unix, the return value is the sum of user+system time consumed by - the process, computed via the resource module. This prevents problems - related to the wraparound effect which the time.clock() function has. - - Under Windows the return value is in wall clock seconds. See the - documentation for the time module for more details.""" - - reps = int(reps) - assert reps >=1, 'reps must be >= 1' - if reps==1: - start = clock() - out = func(*args,**kw) - tot_time = clock()-start - else: - rng = range(reps-1) # the last time is executed separately to store output - start = clock() - for dummy in rng: func(*args,**kw) - out = func(*args,**kw) # one last time - tot_time = clock()-start - av_time = tot_time / reps - return tot_time,av_time,out - - -def timings(reps,func,*args,**kw): - """timings(reps,func,*args,**kw) -> (t_total,t_per_call) - - Execute a function reps times, return a tuple with the elapsed total CPU - time in seconds and the time per call. These are just the first two values - in timings_out().""" - - return timings_out(reps,func,*args,**kw)[0:2] - - -def timing(func,*args,**kw): - """timing(func,*args,**kw) -> t_total - - Execute a function once, return the elapsed total CPU time in - seconds. This is just the first value in timings_out().""" - - return timings_out(1,func,*args,**kw)[0] - diff --git a/contrib/python/ipython/py3/IPython/utils/tokenutil.py b/contrib/python/ipython/py3/IPython/utils/tokenutil.py deleted file mode 100644 index 697d2b504a..0000000000 --- a/contrib/python/ipython/py3/IPython/utils/tokenutil.py +++ /dev/null @@ -1,127 +0,0 @@ -"""Token-related utilities""" - -# Copyright (c) IPython Development Team. -# Distributed under the terms of the Modified BSD License. - -from collections import namedtuple -from io import StringIO -from keyword import iskeyword - -import tokenize - - -Token = namedtuple('Token', ['token', 'text', 'start', 'end', 'line']) - -def generate_tokens(readline): - """wrap generate_tokens to catch EOF errors""" - try: - for token in tokenize.generate_tokens(readline): - yield token - except tokenize.TokenError: - # catch EOF error - return - -def line_at_cursor(cell, cursor_pos=0): - """Return the line in a cell at a given cursor position - - Used for calling line-based APIs that don't support multi-line input, yet. - - Parameters - ---------- - cell : str - multiline block of text - cursor_pos : integer - the cursor position - - Returns - ------- - (line, offset): (string, integer) - The line with the current cursor, and the character offset of the start of the line. - """ - offset = 0 - lines = cell.splitlines(True) - for line in lines: - next_offset = offset + len(line) - if not line.endswith('\n'): - # If the last line doesn't have a trailing newline, treat it as if - # it does so that the cursor at the end of the line still counts - # as being on that line. - next_offset += 1 - if next_offset > cursor_pos: - break - offset = next_offset - else: - line = "" - return (line, offset) - -def token_at_cursor(cell, cursor_pos=0): - """Get the token at a given cursor - - Used for introspection. - - Function calls are prioritized, so the token for the callable will be returned - if the cursor is anywhere inside the call. - - Parameters - ---------- - cell : unicode - A block of Python code - cursor_pos : int - The location of the cursor in the block where the token should be found - """ - names = [] - tokens = [] - call_names = [] - - offsets = {1: 0} # lines start at 1 - for tup in generate_tokens(StringIO(cell).readline): - - tok = Token(*tup) - - # token, text, start, end, line = tup - start_line, start_col = tok.start - end_line, end_col = tok.end - if end_line + 1 not in offsets: - # keep track of offsets for each line - lines = tok.line.splitlines(True) - for lineno, line in enumerate(lines, start_line + 1): - if lineno not in offsets: - offsets[lineno] = offsets[lineno-1] + len(line) - - offset = offsets[start_line] - # allow '|foo' to find 'foo' at the beginning of a line - boundary = cursor_pos + 1 if start_col == 0 else cursor_pos - if offset + start_col >= boundary: - # current token starts after the cursor, - # don't consume it - break - - if tok.token == tokenize.NAME and not iskeyword(tok.text): - if names and tokens and tokens[-1].token == tokenize.OP and tokens[-1].text == '.': - names[-1] = "%s.%s" % (names[-1], tok.text) - else: - names.append(tok.text) - elif tok.token == tokenize.OP: - if tok.text == '=' and names: - # don't inspect the lhs of an assignment - names.pop(-1) - if tok.text == '(' and names: - # if we are inside a function call, inspect the function - call_names.append(names[-1]) - elif tok.text == ')' and call_names: - call_names.pop(-1) - - tokens.append(tok) - - if offsets[end_line] + end_col > cursor_pos: - # we found the cursor, stop reading - break - - if call_names: - return call_names[-1] - elif names: - return names[-1] - else: - return '' - - diff --git a/contrib/python/ipython/py3/IPython/utils/traitlets.py b/contrib/python/ipython/py3/IPython/utils/traitlets.py deleted file mode 100644 index 2f979fa727..0000000000 --- a/contrib/python/ipython/py3/IPython/utils/traitlets.py +++ /dev/null @@ -1,6 +0,0 @@ - -from warnings import warn - -warn("IPython.utils.traitlets has moved to a top-level traitlets package.", stacklevel=2) - -from traitlets import * diff --git a/contrib/python/ipython/py3/IPython/utils/tz.py b/contrib/python/ipython/py3/IPython/utils/tz.py deleted file mode 100644 index b315d532d1..0000000000 --- a/contrib/python/ipython/py3/IPython/utils/tz.py +++ /dev/null @@ -1,46 +0,0 @@ -# encoding: utf-8 -""" -Timezone utilities - -Just UTC-awareness right now -""" - -#----------------------------------------------------------------------------- -# Copyright (C) 2013 The IPython Development Team -# -# Distributed under the terms of the BSD License. The full license is in -# the file COPYING, distributed as part of this software. -#----------------------------------------------------------------------------- - -#----------------------------------------------------------------------------- -# Imports -#----------------------------------------------------------------------------- - -from datetime import tzinfo, timedelta, datetime - -#----------------------------------------------------------------------------- -# Code -#----------------------------------------------------------------------------- -# constant for zero offset -ZERO = timedelta(0) - -class tzUTC(tzinfo): - """tzinfo object for UTC (zero offset)""" - - def utcoffset(self, d): - return ZERO - - def dst(self, d): - return ZERO - -UTC = tzUTC() - -def utc_aware(unaware): - """decorator for adding UTC tzinfo to datetime's utcfoo methods""" - def utc_method(*args, **kwargs): - dt = unaware(*args, **kwargs) - return dt.replace(tzinfo=UTC) - return utc_method - -utcfromtimestamp = utc_aware(datetime.utcfromtimestamp) -utcnow = utc_aware(datetime.utcnow) diff --git a/contrib/python/ipython/py3/IPython/utils/ulinecache.py b/contrib/python/ipython/py3/IPython/utils/ulinecache.py deleted file mode 100644 index 0b4ede08e6..0000000000 --- a/contrib/python/ipython/py3/IPython/utils/ulinecache.py +++ /dev/null @@ -1,21 +0,0 @@ -""" -This module has been deprecated since IPython 6.0. - -Wrapper around linecache which decodes files to unicode according to PEP 263. -""" -import functools -import linecache -from warnings import warn - -getline = linecache.getline - -# getlines has to be looked up at runtime, because doctests monkeypatch it. -@functools.wraps(linecache.getlines) -def getlines(filename, module_globals=None): - """ - Deprecated since IPython 6.0 - """ - warn(("`IPython.utils.ulinecache.getlines` is deprecated since" - " IPython 6.0 and will be removed in future versions."), - DeprecationWarning, stacklevel=2) - return linecache.getlines(filename, module_globals=module_globals) diff --git a/contrib/python/ipython/py3/IPython/utils/version.py b/contrib/python/ipython/py3/IPython/utils/version.py deleted file mode 100644 index 8c65c78e15..0000000000 --- a/contrib/python/ipython/py3/IPython/utils/version.py +++ /dev/null @@ -1,43 +0,0 @@ -# encoding: utf-8 -""" -Utilities for version comparison - -It is a bit ridiculous that we need these. -""" - -#----------------------------------------------------------------------------- -# Copyright (C) 2013 The IPython Development Team -# -# Distributed under the terms of the BSD License. The full license is in -# the file COPYING, distributed as part of this software. -#----------------------------------------------------------------------------- - -from warnings import warn - -warn( - "The `IPython.utils.version` module has been deprecated since IPython 8.0.", - DeprecationWarning, -) - - -def check_version(v, check): - """check version string v >= check - - If dev/prerelease tags result in TypeError for string-number comparison, - it is assumed that the dependency is satisfied. - Users on dev branches are responsible for keeping their own packages up to date. - """ - warn( - "`check_version` function is deprecated as of IPython 8.0" - "and will be removed in future versions.", - DeprecationWarning, - stacklevel=2, - ) - - from distutils.version import LooseVersion - - try: - return LooseVersion(v) >= LooseVersion(check) - except TypeError: - return True - diff --git a/contrib/python/ipython/py3/IPython/utils/wildcard.py b/contrib/python/ipython/py3/IPython/utils/wildcard.py deleted file mode 100644 index cbef8c5175..0000000000 --- a/contrib/python/ipython/py3/IPython/utils/wildcard.py +++ /dev/null @@ -1,111 +0,0 @@ -# -*- coding: utf-8 -*- -"""Support for wildcard pattern matching in object inspection. - -Authors -------- -- Jörgen Stenarson <jorgen.stenarson@bostream.nu> -- Thomas Kluyver -""" - -#***************************************************************************** -# Copyright (C) 2005 Jörgen Stenarson <jorgen.stenarson@bostream.nu> -# -# Distributed under the terms of the BSD License. The full license is in -# the file COPYING, distributed as part of this software. -#***************************************************************************** - -import re -import types - -from IPython.utils.dir2 import dir2 - -def create_typestr2type_dicts(dont_include_in_type2typestr=["lambda"]): - """Return dictionaries mapping lower case typename (e.g. 'tuple') to type - objects from the types package, and vice versa.""" - typenamelist = [tname for tname in dir(types) if tname.endswith("Type")] - typestr2type, type2typestr = {}, {} - - for tname in typenamelist: - name = tname[:-4].lower() # Cut 'Type' off the end of the name - obj = getattr(types, tname) - typestr2type[name] = obj - if name not in dont_include_in_type2typestr: - type2typestr[obj] = name - return typestr2type, type2typestr - -typestr2type, type2typestr = create_typestr2type_dicts() - -def is_type(obj, typestr_or_type): - """is_type(obj, typestr_or_type) verifies if obj is of a certain type. It - can take strings or actual python types for the second argument, i.e. - 'tuple'<->TupleType. 'all' matches all types. - - TODO: Should be extended for choosing more than one type.""" - if typestr_or_type == "all": - return True - if type(typestr_or_type) == type: - test_type = typestr_or_type - else: - test_type = typestr2type.get(typestr_or_type, False) - if test_type: - return isinstance(obj, test_type) - return False - -def show_hidden(str, show_all=False): - """Return true for strings starting with single _ if show_all is true.""" - return show_all or str.startswith("__") or not str.startswith("_") - -def dict_dir(obj): - """Produce a dictionary of an object's attributes. Builds on dir2 by - checking that a getattr() call actually succeeds.""" - ns = {} - for key in dir2(obj): - # This seemingly unnecessary try/except is actually needed - # because there is code out there with metaclasses that - # create 'write only' attributes, where a getattr() call - # will fail even if the attribute appears listed in the - # object's dictionary. Properties can actually do the same - # thing. In particular, Traits use this pattern - try: - ns[key] = getattr(obj, key) - except AttributeError: - pass - return ns - -def filter_ns(ns, name_pattern="*", type_pattern="all", ignore_case=True, - show_all=True): - """Filter a namespace dictionary by name pattern and item type.""" - pattern = name_pattern.replace("*",".*").replace("?",".") - if ignore_case: - reg = re.compile(pattern+"$", re.I) - else: - reg = re.compile(pattern+"$") - - # Check each one matches regex; shouldn't be hidden; of correct type. - return dict((key,obj) for key, obj in ns.items() if reg.match(key) \ - and show_hidden(key, show_all) \ - and is_type(obj, type_pattern) ) - -def list_namespace(namespace, type_pattern, filter, ignore_case=False, show_all=False): - """Return dictionary of all objects in a namespace dictionary that match - type_pattern and filter.""" - pattern_list=filter.split(".") - if len(pattern_list) == 1: - return filter_ns(namespace, name_pattern=pattern_list[0], - type_pattern=type_pattern, - ignore_case=ignore_case, show_all=show_all) - else: - # This is where we can change if all objects should be searched or - # only modules. Just change the type_pattern to module to search only - # modules - filtered = filter_ns(namespace, name_pattern=pattern_list[0], - type_pattern="all", - ignore_case=ignore_case, show_all=show_all) - results = {} - for name, obj in filtered.items(): - ns = list_namespace(dict_dir(obj), type_pattern, - ".".join(pattern_list[1:]), - ignore_case=ignore_case, show_all=show_all) - for inner_name, inner_obj in ns.items(): - results["%s.%s"%(name,inner_name)] = inner_obj - return results |