From a6a92afe03e02795227d2641b49819b687f088f8 Mon Sep 17 00:00:00 2001 From: Mikhail Borisov Date: Thu, 10 Feb 2022 16:45:39 +0300 Subject: Restoring authorship annotation for Mikhail Borisov . Commit 1 of 2. --- contrib/python/ipython/py2/COPYING.rst | 148 +- contrib/python/ipython/py2/IPython/__init__.py | 292 +- contrib/python/ipython/py2/IPython/__main__.py | 28 +- contrib/python/ipython/py2/IPython/config.py | 36 +- contrib/python/ipython/py2/IPython/consoleapp.py | 24 +- contrib/python/ipython/py2/IPython/core/alias.py | 508 +- .../python/ipython/py2/IPython/core/application.py | 754 +-- .../python/ipython/py2/IPython/core/autocall.py | 140 +- .../ipython/py2/IPython/core/builtin_trap.py | 226 +- .../python/ipython/py2/IPython/core/compilerop.py | 286 +- .../python/ipython/py2/IPython/core/completer.py | 2128 +++---- .../ipython/py2/IPython/core/completerlib.py | 686 +-- .../ipython/py2/IPython/core/crashhandler.py | 432 +- .../python/ipython/py2/IPython/core/debugger.py | 1070 ++-- contrib/python/ipython/py2/IPython/core/display.py | 1856 +++---- .../ipython/py2/IPython/core/display_trap.py | 140 +- .../python/ipython/py2/IPython/core/displayhook.py | 560 +- .../python/ipython/py2/IPython/core/displaypub.py | 206 +- contrib/python/ipython/py2/IPython/core/error.py | 120 +- contrib/python/ipython/py2/IPython/core/events.py | 260 +- .../python/ipython/py2/IPython/core/excolors.py | 290 +- .../python/ipython/py2/IPython/core/extensions.py | 322 +- .../python/ipython/py2/IPython/core/formatters.py | 1802 +++--- .../python/ipython/py2/IPython/core/getipython.py | 48 +- contrib/python/ipython/py2/IPython/core/history.py | 1686 +++--- .../python/ipython/py2/IPython/core/historyapp.py | 298 +- contrib/python/ipython/py2/IPython/core/hooks.py | 424 +- .../ipython/py2/IPython/core/inputsplitter.py | 1362 ++--- .../ipython/py2/IPython/core/inputtransformer.py | 1088 ++-- .../ipython/py2/IPython/core/interactiveshell.py | 5856 ++++++++++---------- .../ipython/py2/IPython/core/latex_symbols.py | 2600 ++++----- contrib/python/ipython/py2/IPython/core/logger.py | 442 +- contrib/python/ipython/py2/IPython/core/macro.py | 114 +- contrib/python/ipython/py2/IPython/core/magic.py | 1344 ++--- .../ipython/py2/IPython/core/magic_arguments.py | 556 +- .../ipython/py2/IPython/core/magics/__init__.py | 82 +- .../python/ipython/py2/IPython/core/magics/auto.py | 256 +- .../ipython/py2/IPython/core/magics/basic.py | 1094 ++-- .../python/ipython/py2/IPython/core/magics/code.py | 1420 ++--- .../ipython/py2/IPython/core/magics/config.py | 314 +- .../ipython/py2/IPython/core/magics/display.py | 98 +- .../ipython/py2/IPython/core/magics/execution.py | 2616 ++++----- .../ipython/py2/IPython/core/magics/extension.py | 134 +- .../ipython/py2/IPython/core/magics/history.py | 636 +-- .../ipython/py2/IPython/core/magics/logging.py | 366 +- .../ipython/py2/IPython/core/magics/namespace.py | 1408 ++--- .../python/ipython/py2/IPython/core/magics/osm.py | 1572 +++--- .../ipython/py2/IPython/core/magics/pylab.py | 332 +- .../ipython/py2/IPython/core/magics/script.py | 528 +- .../python/ipython/py2/IPython/core/oinspect.py | 1652 +++--- contrib/python/ipython/py2/IPython/core/page.py | 738 +-- contrib/python/ipython/py2/IPython/core/payload.py | 110 +- .../python/ipython/py2/IPython/core/payloadpage.py | 104 +- .../python/ipython/py2/IPython/core/prefilter.py | 1356 ++--- .../py2/IPython/core/profile/README_STARTUP | 22 +- .../python/ipython/py2/IPython/core/profileapp.py | 606 +- .../python/ipython/py2/IPython/core/profiledir.py | 402 +- contrib/python/ipython/py2/IPython/core/prompts.py | 48 +- .../python/ipython/py2/IPython/core/pylabtools.py | 756 +-- contrib/python/ipython/py2/IPython/core/release.py | 234 +- .../python/ipython/py2/IPython/core/shadowns.py | 2 +- .../python/ipython/py2/IPython/core/shellapp.py | 724 +-- .../python/ipython/py2/IPython/core/splitinput.py | 274 +- contrib/python/ipython/py2/IPython/core/ultratb.py | 2874 +++++----- contrib/python/ipython/py2/IPython/core/usage.py | 648 +-- contrib/python/ipython/py2/IPython/display.py | 32 +- .../ipython/py2/IPython/extensions/__init__.py | 4 +- .../ipython/py2/IPython/extensions/autoreload.py | 1068 ++-- .../ipython/py2/IPython/extensions/cythonmagic.py | 42 +- .../ipython/py2/IPython/extensions/rmagic.py | 24 +- .../ipython/py2/IPython/extensions/storemagic.py | 448 +- .../py2/IPython/extensions/sympyprinting.py | 64 +- .../ipython/py2/IPython/external/__init__.py | 10 +- .../py2/IPython/external/decorators/__init__.py | 18 +- .../py2/IPython/external/decorators/_decorators.py | 562 +- .../decorators/_numpy_testing_noseclasses.py | 82 +- .../external/decorators/_numpy_testing_utils.py | 218 +- .../python/ipython/py2/IPython/external/mathjax.py | 26 +- .../ipython/py2/IPython/external/qt_for_kernel.py | 182 +- .../ipython/py2/IPython/external/qt_loaders.py | 562 +- contrib/python/ipython/py2/IPython/frontend.py | 56 +- contrib/python/ipython/py2/IPython/html.py | 54 +- .../python/ipython/py2/IPython/kernel/__init__.py | 68 +- .../python/ipython/py2/IPython/kernel/__main__.py | 6 +- .../python/ipython/py2/IPython/kernel/adapter.py | 2 +- .../python/ipython/py2/IPython/kernel/channels.py | 2 +- .../ipython/py2/IPython/kernel/channelsabc.py | 2 +- .../python/ipython/py2/IPython/kernel/client.py | 2 +- .../python/ipython/py2/IPython/kernel/clientabc.py | 2 +- .../python/ipython/py2/IPython/kernel/connect.py | 4 +- .../ipython/py2/IPython/kernel/kernelspec.py | 2 +- .../ipython/py2/IPython/kernel/kernelspecapp.py | 2 +- .../python/ipython/py2/IPython/kernel/launcher.py | 2 +- .../python/ipython/py2/IPython/kernel/manager.py | 2 +- .../ipython/py2/IPython/kernel/managerabc.py | 2 +- .../py2/IPython/kernel/multikernelmanager.py | 2 +- .../python/ipython/py2/IPython/kernel/restarter.py | 2 +- .../python/ipython/py2/IPython/kernel/threaded.py | 2 +- contrib/python/ipython/py2/IPython/lib/__init__.py | 42 +- .../ipython/py2/IPython/lib/backgroundjobs.py | 980 ++-- .../python/ipython/py2/IPython/lib/clipboard.py | 144 +- .../python/ipython/py2/IPython/lib/deepreload.py | 712 +-- contrib/python/ipython/py2/IPython/lib/demo.py | 1136 ++-- contrib/python/ipython/py2/IPython/lib/display.py | 1106 ++-- .../python/ipython/py2/IPython/lib/editorhooks.py | 256 +- .../python/ipython/py2/IPython/lib/guisupport.py | 274 +- .../python/ipython/py2/IPython/lib/inputhook.py | 1096 ++-- .../ipython/py2/IPython/lib/inputhookglut.py | 346 +- .../python/ipython/py2/IPython/lib/inputhookgtk.py | 70 +- .../ipython/py2/IPython/lib/inputhookgtk3.py | 68 +- .../ipython/py2/IPython/lib/inputhookpyglet.py | 222 +- .../python/ipython/py2/IPython/lib/inputhookqt4.py | 360 +- .../python/ipython/py2/IPython/lib/inputhookwx.py | 334 +- contrib/python/ipython/py2/IPython/lib/kernel.py | 26 +- .../python/ipython/py2/IPython/lib/latextools.py | 380 +- contrib/python/ipython/py2/IPython/lib/lexers.py | 1000 ++-- contrib/python/ipython/py2/IPython/lib/pretty.py | 1626 +++--- contrib/python/ipython/py2/IPython/lib/security.py | 228 +- contrib/python/ipython/py2/IPython/nbconvert.py | 36 +- contrib/python/ipython/py2/IPython/nbformat.py | 36 +- contrib/python/ipython/py2/IPython/parallel.py | 38 +- contrib/python/ipython/py2/IPython/paths.py | 240 +- contrib/python/ipython/py2/IPython/qt.py | 46 +- .../py2/IPython/sphinxext/custom_doctests.py | 310 +- .../sphinxext/ipython_console_highlighting.py | 56 +- .../py2/IPython/sphinxext/ipython_directive.py | 2322 ++++---- .../python/ipython/py2/IPython/terminal/console.py | 36 +- .../python/ipython/py2/IPython/terminal/embed.py | 536 +- .../py2/IPython/terminal/interactiveshell.py | 236 +- .../python/ipython/py2/IPython/terminal/ipapp.py | 674 +-- .../python/ipython/py2/IPython/testing/__init__.py | 76 +- .../python/ipython/py2/IPython/testing/__main__.py | 6 +- .../ipython/py2/IPython/testing/decorators.py | 740 +-- .../ipython/py2/IPython/testing/globalipapp.py | 258 +- .../python/ipython/py2/IPython/testing/iptest.py | 856 +-- .../py2/IPython/testing/iptestcontroller.py | 1064 ++-- .../ipython/py2/IPython/testing/ipunittest.py | 352 +- .../ipython/py2/IPython/testing/plugin/Makefile | 148 +- .../ipython/py2/IPython/testing/plugin/README.txt | 78 +- .../py2/IPython/testing/plugin/dtexample.py | 316 +- .../py2/IPython/testing/plugin/ipdoctest.py | 1522 ++--- .../ipython/py2/IPython/testing/plugin/iptest.py | 38 +- .../ipython/py2/IPython/testing/plugin/setup.py | 36 +- .../py2/IPython/testing/plugin/show_refs.py | 40 +- .../ipython/py2/IPython/testing/plugin/simple.py | 68 +- .../py2/IPython/testing/plugin/simplevars.py | 6 +- .../py2/IPython/testing/plugin/test_combo.txt | 72 +- .../py2/IPython/testing/plugin/test_example.txt | 48 +- .../py2/IPython/testing/plugin/test_exampleip.txt | 60 +- .../py2/IPython/testing/plugin/test_ipdoctest.py | 160 +- .../py2/IPython/testing/plugin/test_refs.py | 92 +- .../ipython/py2/IPython/testing/skipdoctest.py | 76 +- .../python/ipython/py2/IPython/testing/tools.py | 892 +-- .../python/ipython/py2/IPython/utils/PyColorize.py | 680 +-- .../ipython/py2/IPython/utils/_process_cli.py | 156 +- .../ipython/py2/IPython/utils/_process_common.py | 428 +- .../ipython/py2/IPython/utils/_process_posix.py | 450 +- .../ipython/py2/IPython/utils/_process_win32.py | 384 +- .../py2/IPython/utils/_process_win32_controller.py | 1154 ++-- .../ipython/py2/IPython/utils/_signatures.py | 1626 +++--- .../python/ipython/py2/IPython/utils/_sysinfo.py | 2 +- .../ipython/py2/IPython/utils/_tokenize_py2.py | 878 +-- .../ipython/py2/IPython/utils/_tokenize_py3.py | 1190 ++-- .../python/ipython/py2/IPython/utils/capture.py | 312 +- .../python/ipython/py2/IPython/utils/coloransi.py | 374 +- .../python/ipython/py2/IPython/utils/contexts.py | 126 +- .../python/ipython/py2/IPython/utils/daemonize.py | 8 +- contrib/python/ipython/py2/IPython/utils/data.py | 74 +- .../python/ipython/py2/IPython/utils/decorators.py | 116 +- contrib/python/ipython/py2/IPython/utils/dir2.py | 90 +- .../python/ipython/py2/IPython/utils/encoding.py | 142 +- .../python/ipython/py2/IPython/utils/eventful.py | 14 +- contrib/python/ipython/py2/IPython/utils/frame.py | 196 +- .../python/ipython/py2/IPython/utils/generics.py | 68 +- .../ipython/py2/IPython/utils/importstring.py | 78 +- contrib/python/ipython/py2/IPython/utils/io.py | 440 +- .../python/ipython/py2/IPython/utils/ipstruct.py | 782 +-- .../python/ipython/py2/IPython/utils/jsonutil.py | 10 +- .../ipython/py2/IPython/utils/localinterfaces.py | 10 +- contrib/python/ipython/py2/IPython/utils/log.py | 14 +- .../ipython/py2/IPython/utils/module_paths.py | 250 +- contrib/python/ipython/py2/IPython/utils/openpy.py | 496 +- contrib/python/ipython/py2/IPython/utils/path.py | 862 +-- .../python/ipython/py2/IPython/utils/pickleutil.py | 10 +- .../python/ipython/py2/IPython/utils/process.py | 212 +- .../python/ipython/py2/IPython/utils/py3compat.py | 668 +-- .../python/ipython/py2/IPython/utils/rlineimpl.py | 148 +- .../python/ipython/py2/IPython/utils/sentinel.py | 34 +- .../python/ipython/py2/IPython/utils/shimmodule.py | 184 +- .../python/ipython/py2/IPython/utils/signatures.py | 22 +- .../ipython/py2/IPython/utils/strdispatch.py | 136 +- .../python/ipython/py2/IPython/utils/sysinfo.py | 334 +- .../ipython/py2/IPython/utils/syspathcontext.py | 142 +- .../python/ipython/py2/IPython/utils/tempdir.py | 290 +- .../python/ipython/py2/IPython/utils/terminal.py | 222 +- contrib/python/ipython/py2/IPython/utils/text.py | 1552 +++--- contrib/python/ipython/py2/IPython/utils/timing.py | 236 +- .../python/ipython/py2/IPython/utils/tokenize2.py | 18 +- .../python/ipython/py2/IPython/utils/tokenutil.py | 254 +- .../python/ipython/py2/IPython/utils/traitlets.py | 14 +- contrib/python/ipython/py2/IPython/utils/tz.py | 92 +- .../python/ipython/py2/IPython/utils/ulinecache.py | 90 +- .../python/ipython/py2/IPython/utils/version.py | 72 +- contrib/python/ipython/py2/IPython/utils/warn.py | 92 +- .../python/ipython/py2/IPython/utils/wildcard.py | 224 +- contrib/python/ipython/py2/bin/ya.make | 10 +- contrib/python/ipython/ya.make | 4 +- 207 files changed, 45770 insertions(+), 45770 deletions(-) (limited to 'contrib/python/ipython') diff --git a/contrib/python/ipython/py2/COPYING.rst b/contrib/python/ipython/py2/COPYING.rst index 59674acdc8d..2a973f9dcb7 100644 --- a/contrib/python/ipython/py2/COPYING.rst +++ b/contrib/python/ipython/py2/COPYING.rst @@ -1,74 +1,74 @@ -============================= - The IPython licensing terms -============================= - -IPython is licensed under the terms of the Modified BSD License (also known as -New or Revised or 3-Clause BSD), as follows: - -- Copyright (c) 2008-2014, IPython Development Team -- Copyright (c) 2001-2007, Fernando Perez -- Copyright (c) 2001, Janko Hauser -- Copyright (c) 2001, Nathaniel Gray - -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 IPython Development Team 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 OWNER 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. - -About the IPython Development Team ----------------------------------- - -Fernando Perez began IPython in 2001 based on code from Janko Hauser - and Nathaniel Gray . Fernando is still -the project lead. - -The IPython Development Team is the set of all contributors to the IPython -project. This includes all of the IPython subprojects. A full list with -details is kept in the documentation directory, in the file -``about/credits.txt``. - -The core team that coordinates development on GitHub can be found here: -https://github.com/ipython/. - -Our Copyright Policy --------------------- - -IPython uses a shared copyright model. Each contributor maintains copyright -over their contributions to IPython. But, it is important to note that these -contributions are typically only changes to the repositories. Thus, the IPython -source code, in its entirety is not the copyright of any single person or -institution. Instead, it is the collective copyright of the entire IPython -Development Team. If individual contributors want to maintain a record of what -changes/contributions they have specific copyright on, they should indicate -their copyright in the commit message of the change, when they commit the -change to one of the IPython repositories. - -With this in mind, the following banner should be used in any source code file -to indicate the copyright and license terms: - -:: - - # Copyright (c) IPython Development Team. - # Distributed under the terms of the Modified BSD License. +============================= + The IPython licensing terms +============================= + +IPython is licensed under the terms of the Modified BSD License (also known as +New or Revised or 3-Clause BSD), as follows: + +- Copyright (c) 2008-2014, IPython Development Team +- Copyright (c) 2001-2007, Fernando Perez +- Copyright (c) 2001, Janko Hauser +- Copyright (c) 2001, Nathaniel Gray + +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 IPython Development Team 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 OWNER 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. + +About the IPython Development Team +---------------------------------- + +Fernando Perez began IPython in 2001 based on code from Janko Hauser + and Nathaniel Gray . Fernando is still +the project lead. + +The IPython Development Team is the set of all contributors to the IPython +project. This includes all of the IPython subprojects. A full list with +details is kept in the documentation directory, in the file +``about/credits.txt``. + +The core team that coordinates development on GitHub can be found here: +https://github.com/ipython/. + +Our Copyright Policy +-------------------- + +IPython uses a shared copyright model. Each contributor maintains copyright +over their contributions to IPython. But, it is important to note that these +contributions are typically only changes to the repositories. Thus, the IPython +source code, in its entirety is not the copyright of any single person or +institution. Instead, it is the collective copyright of the entire IPython +Development Team. If individual contributors want to maintain a record of what +changes/contributions they have specific copyright on, they should indicate +their copyright in the commit message of the change, when they commit the +change to one of the IPython repositories. + +With this in mind, the following banner should be used in any source code file +to indicate the copyright and license terms: + +:: + + # Copyright (c) IPython Development Team. + # Distributed under the terms of the Modified BSD License. diff --git a/contrib/python/ipython/py2/IPython/__init__.py b/contrib/python/ipython/py2/IPython/__init__.py index 9b450da6a0c..aa5121da24c 100644 --- a/contrib/python/ipython/py2/IPython/__init__.py +++ b/contrib/python/ipython/py2/IPython/__init__.py @@ -1,146 +1,146 @@ -# encoding: utf-8 -""" -IPython: tools for interactive and parallel computing in Python. - -http://ipython.org -""" -#----------------------------------------------------------------------------- -# Copyright (c) 2008-2011, IPython Development Team. -# Copyright (c) 2001-2007, Fernando Perez -# Copyright (c) 2001, Janko Hauser -# Copyright (c) 2001, Nathaniel Gray -# -# Distributed under the terms of the Modified BSD License. -# -# The full license is in the file COPYING.txt, distributed with this software. -#----------------------------------------------------------------------------- - -#----------------------------------------------------------------------------- -# Imports -#----------------------------------------------------------------------------- -from __future__ import absolute_import - -import os -import sys -import warnings - -#----------------------------------------------------------------------------- -# Setup everything -#----------------------------------------------------------------------------- - -# Don't forget to also update setup.py when this changes! -v = sys.version_info -if v[:2] < (2,7) or (v[0] >= 3 and v[:2] < (3,3)): - raise ImportError('IPython requires Python version 2.7 or 3.3 or above.') -del v - -# Make it easy to import extensions - they are always directly on pythonpath. -# Therefore, non-IPython modules can be added to extensions directory. -# This should probably be in ipapp.py. -sys.path.append(os.path.join(os.path.dirname(__file__), "extensions")) - -#----------------------------------------------------------------------------- -# 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 .testing import test -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 - -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 : 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`. - """ - from IPython.kernel.zmq.kernelapp import launch_new_instance - return launch_new_instance(argv=argv, **kwargs) - +# encoding: utf-8 +""" +IPython: tools for interactive and parallel computing in Python. + +http://ipython.org +""" +#----------------------------------------------------------------------------- +# Copyright (c) 2008-2011, IPython Development Team. +# Copyright (c) 2001-2007, Fernando Perez +# Copyright (c) 2001, Janko Hauser +# Copyright (c) 2001, Nathaniel Gray +# +# Distributed under the terms of the Modified BSD License. +# +# The full license is in the file COPYING.txt, distributed with this software. +#----------------------------------------------------------------------------- + +#----------------------------------------------------------------------------- +# Imports +#----------------------------------------------------------------------------- +from __future__ import absolute_import + +import os +import sys +import warnings + +#----------------------------------------------------------------------------- +# Setup everything +#----------------------------------------------------------------------------- + +# Don't forget to also update setup.py when this changes! +v = sys.version_info +if v[:2] < (2,7) or (v[0] >= 3 and v[:2] < (3,3)): + raise ImportError('IPython requires Python version 2.7 or 3.3 or above.') +del v + +# Make it easy to import extensions - they are always directly on pythonpath. +# Therefore, non-IPython modules can be added to extensions directory. +# This should probably be in ipapp.py. +sys.path.append(os.path.join(os.path.dirname(__file__), "extensions")) + +#----------------------------------------------------------------------------- +# 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 .testing import test +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 + +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 : 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`. + """ + from IPython.kernel.zmq.kernelapp import launch_new_instance + return launch_new_instance(argv=argv, **kwargs) + diff --git a/contrib/python/ipython/py2/IPython/__main__.py b/contrib/python/ipython/py2/IPython/__main__.py index d5123f33a20..2e142249b53 100644 --- a/contrib/python/ipython/py2/IPython/__main__.py +++ b/contrib/python/ipython/py2/IPython/__main__.py @@ -1,14 +1,14 @@ -# 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() +# 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/py2/IPython/config.py b/contrib/python/ipython/py2/IPython/config.py index cf2bacafad1..ac8d0aa4bd9 100644 --- a/contrib/python/ipython/py2/IPython/config.py +++ b/contrib/python/ipython/py2/IPython/config.py @@ -1,19 +1,19 @@ -""" -Shim to maintain backwards compatibility with old IPython.config 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 - +""" +Shim to maintain backwards compatibility with old IPython.config 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.config` package has been deprecated since IPython 4.0. " - "You should import from traitlets.config instead.", ShimWarning) - - -# Unconditionally insert the shim into sys.modules so that further import calls -# trigger the custom attribute access above - -sys.modules['IPython.config'] = ShimModule(src='IPython.config', mirror='traitlets.config') + "You should import from traitlets.config instead.", ShimWarning) + + +# Unconditionally insert the shim into sys.modules so that further import calls +# trigger the custom attribute access above + +sys.modules['IPython.config'] = ShimModule(src='IPython.config', mirror='traitlets.config') diff --git a/contrib/python/ipython/py2/IPython/consoleapp.py b/contrib/python/ipython/py2/IPython/consoleapp.py index 14903bdc74c..e2ffbbf664a 100644 --- a/contrib/python/ipython/py2/IPython/consoleapp.py +++ b/contrib/python/ipython/py2/IPython/consoleapp.py @@ -1,12 +1,12 @@ -""" -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. " - "You should import from jupyter_client.consoleapp instead.") - -from jupyter_client.consoleapp import * +""" +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. " + "You should import from jupyter_client.consoleapp instead.") + +from jupyter_client.consoleapp import * diff --git a/contrib/python/ipython/py2/IPython/core/alias.py b/contrib/python/ipython/py2/IPython/core/alias.py index 28a9ccb00d6..66ba986b40f 100644 --- a/contrib/python/ipython/py2/IPython/core/alias.py +++ b/contrib/python/ipython/py2/IPython/core/alias.py @@ -1,257 +1,257 @@ -# 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 IPython.core.error import UsageError - -from IPython.utils.py3compat import string_types -from traitlets import List, Instance +# 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 IPython.core.error import UsageError + +from IPython.utils.py3compat import string_types +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, string_types)): - 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 "".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): - + +#----------------------------------------------------------------------------- +# 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, string_types)): + 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 "".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: - 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) + 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: + 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/py2/IPython/core/application.py b/contrib/python/ipython/py2/IPython/core/application.py index af281339451..99e94a342a9 100644 --- a/contrib/python/ipython/py2/IPython/core/application.py +++ b/contrib/python/ipython/py2/IPython/core/application.py @@ -1,49 +1,49 @@ -# 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 +# 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 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 IPython.utils import py3compat +import glob +import logging +import os +import shutil +import sys + +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 IPython.utils import py3compat from traitlets import ( List, Unicode, Type, Bool, Dict, Set, Instance, Undefined, default, observe, ) - -if os.name == 'nt': - programdata = os.environ.get('PROGRAMDATA', None) - if programdata: - SYSTEM_CONFIG_DIRS = [os.path.join(programdata, 'ipython')] - else: # PROGRAMDATA is not defined by default on XP. - SYSTEM_CONFIG_DIRS = [] -else: - SYSTEM_CONFIG_DIRS = [ - "/usr/local/etc/ipython", - "/etc/ipython", - ] - + +if os.name == 'nt': + programdata = os.environ.get('PROGRAMDATA', None) + if programdata: + SYSTEM_CONFIG_DIRS = [os.path.join(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') @@ -62,241 +62,241 @@ else: 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 = { - '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( - 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 ` 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 = Unicode(u'ipython') - description = Unicode(u'IPython: an enhanced interactive Python shell.') - version = Unicode(release.version) - - aliases = Dict(base_aliases) - flags = Dict(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() + +# aliases and flags + +base_aliases = { + '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( + 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 ` 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 = Unicode(u'ipython') + description = Unicode(u'IPython: an enhanced interactive Python shell.') + version = Unicode(release.version) + + aliases = Dict(base_aliases) + flags = Dict(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' + 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()) + + # 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 [py3compat.getcwd()] - + def _config_file_paths_default(self): + return [py3compat.getcwd()] + 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. + 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) - + 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.""" + help="""The IPython profile to use.""" ).tag(config=True) @observe('profile') def _profile_changed(self, change): - self.builtin_profile_dir = os.path.join( + self.builtin_profile_dir = os.path.join( get_ipython_package_dir(), u'config', u'profile', change['new'] - ) - + ) + 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. - """ + 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() + 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) + 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 - + 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()) + + config_files = List(Unicode()) @default('config_files') - def _config_files_default(self): - return [self.config_file_name] - + 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. + 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 + 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: - py3compat.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 - #------------------------------------------------------------------------- - - deprecated_subcommands = {} - - def initialize_subcommand(self, subc, argv=None): - if subc in self.deprecated_subcommands: - self.log.warning("Subcommand `ipython {sub}` is deprecated and will be removed " - "in future versions.".format(sub=subc)) + + # 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: + py3compat.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 + #------------------------------------------------------------------------- + + deprecated_subcommands = {} + + def initialize_subcommand(self, subc, argv=None): + if subc in self.deprecated_subcommands: + self.log.warning("Subcommand `ipython {sub}` is deprecated and will be removed " + "in future versions.".format(sub=subc)) self.log.warning("You likely want to use `jupyter {sub}` in the " "future".format(sub=subc)) - return super(BaseIPythonApplication, self).initialize_subcommand(subc, argv) - - 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) + return super(BaseIPythonApplication, self).initialize_subcommand(subc, argv) + + 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 = py3compat.cast_bytes_py2(os.path.abspath(old), - sys.getfilesystemencoding() - ) - if str_old in sys.path: - sys.path.remove(str_old) - str_path = py3compat.cast_bytes_py2(os.path.abspath(new), - sys.getfilesystemencoding() - ) - sys.path.append(str_path) - ensure_dir_exists(new) - readme = os.path.join(new, 'README') - readme_src = os.path.join(get_ipython_package_dir(), u'config', u'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) - + if old is not Undefined: + str_old = py3compat.cast_bytes_py2(os.path.abspath(old), + sys.getfilesystemencoding() + ) + if str_old in sys.path: + sys.path.remove(str_old) + str_path = py3compat.cast_bytes_py2(os.path.abspath(new), + sys.getfilesystemencoding() + ) + sys.path.append(str_path) + ensure_dir_exists(new) + readme = os.path.join(new, 'README') + readme_src = os.path.join(get_ipython_package_dir(), u'config', u'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. + """Load the config file. + + By default, errors in loading config are handled, and a warning + printed on screen. For testing, the suppress_errors option is set + to False, so errors will make tests fail. `supress_errors` default value is to be `None` in which case the behavior default to the one of `traitlets.Application`. @@ -307,161 +307,161 @@ class BaseIPythonApplication(Application): - 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: + 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 + 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("Using existing profile dir: %r"%p.location) - 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.info("Using existing profile dir: %r"%location) - # 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.""" + + 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("Using existing profile dir: %r"%p.location) + 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.info("Using existing profile dir: %r"%location) + # 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 = self.builtin_profile_dir - if self.copy_config_files: - src = self.profile - - cfg = self.config_file_name - if path and os.path.exists(os.path.join(path, cfg)): - 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 = glob.glob(os.path.join(path, '*.py')) - for fullpath in files: - cfg = os.path.basename(fullpath) - 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() - fname = os.path.join(self.profile_dir.location, self.config_file_name) - if self.overwrite or not os.path.exists(fname): - self.log.warning("Generating default config file: %r"%(fname)) - with open(fname, 'w') as f: - f.write(s) - - @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 + self.config_file_paths.extend(SYSTEM_CONFIG_DIRS) + # copy config files + path = self.builtin_profile_dir + if self.copy_config_files: + src = self.profile + + cfg = self.config_file_name + if path and os.path.exists(os.path.join(path, cfg)): + 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 = glob.glob(os.path.join(path, '*.py')) + for fullpath in files: + cfg = os.path.basename(fullpath) + 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() + fname = os.path.join(self.profile_dir.location, self.config_file_name) + if self.overwrite or not os.path.exists(fname): + self.log.warning("Generating default config file: %r"%(fname)) + with open(fname, 'w') as f: + f.write(s) + + @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) + 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/py2/IPython/core/autocall.py b/contrib/python/ipython/py2/IPython/core/autocall.py index bab7f859c96..4ef2bce59c1 100644 --- a/contrib/python/ipython/py2/IPython/core/autocall.py +++ b/contrib/python/ipython/py2/IPython/core/autocall.py @@ -1,70 +1,70 @@ -# 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() +# 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/py2/IPython/core/builtin_trap.py b/contrib/python/ipython/py2/IPython/core/builtin_trap.py index 909a555c733..011362599c8 100644 --- a/contrib/python/ipython/py2/IPython/core/builtin_trap.py +++ b/contrib/python/ipython/py2/IPython/core/builtin_trap.py @@ -1,114 +1,114 @@ -""" -A context manager for managing things injected into :mod:`__builtin__`. - -Authors: - -* Brian Granger -* Fernando Perez -""" -#----------------------------------------------------------------------------- -# Copyright (C) 2010-2011 The IPython Development Team. -# -# Distributed under the terms of the BSD License. -# -# Complete license in the file COPYING.txt, distributed with this software. -#----------------------------------------------------------------------------- - -#----------------------------------------------------------------------------- -# Imports -#----------------------------------------------------------------------------- - -from traitlets.config.configurable import Configurable - -from IPython.utils.py3compat import builtin_mod, iteritems -from traitlets import Instance - -#----------------------------------------------------------------------------- -# Classes and functions -#----------------------------------------------------------------------------- - -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, - } - # Recursive reload function - try: - from IPython.lib import deepreload - if self.shell.deep_reload: - from warnings import warn +""" +A context manager for managing things injected into :mod:`__builtin__`. + +Authors: + +* Brian Granger +* Fernando Perez +""" +#----------------------------------------------------------------------------- +# Copyright (C) 2010-2011 The IPython Development Team. +# +# Distributed under the terms of the BSD License. +# +# Complete license in the file COPYING.txt, distributed with this software. +#----------------------------------------------------------------------------- + +#----------------------------------------------------------------------------- +# Imports +#----------------------------------------------------------------------------- + +from traitlets.config.configurable import Configurable + +from IPython.utils.py3compat import builtin_mod, iteritems +from traitlets import Instance + +#----------------------------------------------------------------------------- +# Classes and functions +#----------------------------------------------------------------------------- + +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, + } + # Recursive reload function + try: + from IPython.lib import deepreload + if self.shell.deep_reload: + from warnings import warn warn("Automatically replacing builtin `reload` by `deepreload.reload` is deprecated since IPython 4.0, please import `reload` explicitly from `IPython.lib.deepreload", DeprecationWarning) - self.auto_builtins['reload'] = deepreload._dreload - else: - self.auto_builtins['dreload']= deepreload._dreload - except ImportError: - pass - - 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 iteritems(self.auto_builtins): - 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 iteritems(self._orig_builtins): - remove_builtin(key, val) - self._orig_builtins.clear() - self._builtins_added = False + self.auto_builtins['reload'] = deepreload._dreload + else: + self.auto_builtins['dreload']= deepreload._dreload + except ImportError: + pass + + 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 iteritems(self.auto_builtins): + 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 iteritems(self._orig_builtins): + remove_builtin(key, val) + self._orig_builtins.clear() + self._builtins_added = False diff --git a/contrib/python/ipython/py2/IPython/core/compilerop.py b/contrib/python/ipython/py2/IPython/core/compilerop.py index f529eb52248..f662e37e969 100644 --- a/contrib/python/ipython/py2/IPython/core/compilerop.py +++ b/contrib/python/ipython/py2/IPython/core/compilerop.py @@ -1,144 +1,144 @@ -"""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 -#----------------------------------------------------------------------------- -from __future__ import print_function - -# Stdlib imports -import __future__ -from ast import PyCF_ONLY_AST -import codeop -import functools -import hashlib -import linecache -import operator -import time - -#----------------------------------------------------------------------------- -# Constants -#----------------------------------------------------------------------------- - -# Roughtly 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. - """ +"""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 +#----------------------------------------------------------------------------- +from __future__ import print_function + +# Stdlib imports +import __future__ +from ast import PyCF_ONLY_AST +import codeop +import functools +import hashlib +import linecache +import operator +import time + +#----------------------------------------------------------------------------- +# Constants +#----------------------------------------------------------------------------- + +# Roughtly 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 ''.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 - - def ast_parse(self, source, filename='', 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 cache(self, code, number=0): - """Make a name for a block of code, and cache the code. - - Parameters - ---------- - code : str - The Python source code to cache. - number : int - A number which forms part of the code's name. Used for the execution - counter. - - 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. - """ - name = code_name(code, number) - entry = (len(code), time.time(), - [line+'\n' for line in code.splitlines()], name) - linecache.cache[name] = entry - linecache._ipython_cache[name] = entry - return name - -def check_linecache_ipython(*args): - """Call linecache.checkcache() safely protecting our cached values. - """ - # First call the orignal 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) + # 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 ''.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 + + def ast_parse(self, source, filename='', 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 cache(self, code, number=0): + """Make a name for a block of code, and cache the code. + + Parameters + ---------- + code : str + The Python source code to cache. + number : int + A number which forms part of the code's name. Used for the execution + counter. + + 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. + """ + name = code_name(code, number) + entry = (len(code), time.time(), + [line+'\n' for line in code.splitlines()], name) + linecache.cache[name] = entry + linecache._ipython_cache[name] = entry + return name + +def check_linecache_ipython(*args): + """Call linecache.checkcache() safely protecting our cached values. + """ + # First call the orignal 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/py2/IPython/core/completer.py b/contrib/python/ipython/py2/IPython/core/completer.py index b386945e54e..46003de8d4c 100644 --- a/contrib/python/ipython/py2/IPython/core/completer.py +++ b/contrib/python/ipython/py2/IPython/core/completer.py @@ -1,79 +1,79 @@ -# encoding: utf-8 -"""Word completion for IPython. - +# encoding: utf-8 +"""Word 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 +library. The original enhancements made to rlcompleter have been sent upstream and were accepted as of Python 2.3, - -""" - -# 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 - + +""" + +# 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 + from __future__ import print_function -import __main__ -import glob -import inspect -import itertools -import keyword -import os -import re -import sys -import unicodedata -import string +import __main__ +import glob +import inspect +import itertools +import keyword +import os +import re +import sys +import unicodedata +import string import warnings - + from traitlets.config.configurable import Configurable -from IPython.core.error import TryNext -from IPython.core.inputsplitter import ESC_MAGIC -from IPython.core.latex_symbols import latex_symbols, reverse_latex_symbol -from IPython.utils import generics -from IPython.utils.decorators import undoc +from IPython.core.error import TryNext +from IPython.core.inputsplitter import ESC_MAGIC +from IPython.core.latex_symbols import latex_symbols, reverse_latex_symbol +from IPython.utils import generics +from IPython.utils.decorators import undoc from IPython.utils.dir2 import dir2, get_real_method -from IPython.utils.process import arg_split +from IPython.utils.process import arg_split from IPython.utils.py3compat import builtin_mod, string_types, PY3, cast_unicode_py2 from traitlets import Bool, Enum, observe - - -# Public API -__all__ = ['Completer','IPCompleter'] - -if sys.platform == 'win32': - PROTECTABLES = ' ' -else: - PROTECTABLES = ' ()[]{}?=\\|;:\'#*"^&' - + + +# 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 - -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): - """Escape a string to protect certain characters.""" + +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): + """Escape a string to protect certain characters.""" if set(s) & set(PROTECTABLES): if sys.platform == "win32": return '"' + s + '"' @@ -81,62 +81,62 @@ def protect_filename(s): return "".join(("\\" + c if c in PROTECTABLES else c) for c in s) else: return s - - -def expand_user(path): - """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, tilde_expand, tilde_val): - """Does the opposite of expand_user, with its outputs. - """ - if tilde_expand: - return path.replace(tilde_val, '~') - else: - return path - - + + +def expand_user(path): + """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, tilde_expand, tilde_val): + """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: - + - Lowercase all completions, so they are sorted alphabetically with upper and lower case words mingled - Demote any completions starting with underscores to the end @@ -145,410 +145,410 @@ def completions_sorting_key(word): """ # Case insensitive sort word = word.lower() - + 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:]: + if not "%" in word[2:]: word = word[2:] prio2 = 2 elif word.startswith('%'): - if not "%" in word[1:]: + if not "%" in word[1:]: word = word[1:] prio2 = 1 - + return prio1, word, prio2 + - -@undoc -class Bunch(object): pass - - +@undoc +class Bunch(object): pass + + 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_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 + help="""Activate greedy completion PENDING DEPRECTION. this is now mostly taken care of with Jedi. - - This will enable completion on elements of lists, results of function calls, etc., - but can be unsafe because the code is actually evaluated on TAB. - """ + + 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) - + backslash_combining_completions = Bool(True, help="Enable unicode completions, e.g. \\alpha . " "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. - + 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. - - Completer instances should be used as the completion mechanism of - readline via the set_completer() call: - - readline.set_completer(Completer(my_namespace).complete) - """ - - # 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 = 1 - else: - self.use_main_ns = 0 - 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 - - 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) + + 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. + + Completer instances should be used as the completion mechanism of + readline via the set_completer() call: + + readline.set_completer(Completer(my_namespace).complete) + """ + + # 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 = 1 + else: + self.use_main_ns = 0 + 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 + + 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) return [cast_unicode_py2(m) for m in 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 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 ''. - 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) + + 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 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 ''. + 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: - words = dir2(obj) - - try: - words = generics.complete_object(obj, words) - except TryNext: - pass - except Exception: - # Silence errors from completion function - #raise # dbg - pass - # Build match list to return - n = len(attr) + 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 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 [] - + + +def get__all__entries(obj): + """returns the strings in the __all__ attribute""" + try: + words = getattr(obj, '__all__') + except: + return [] + return [cast_unicode_py2(w) for w in words if isinstance(w, string_types)] - - -def match_dict_keys(keys, prefix, delims): - """Used by dict_key_matches, matching the prefix to a list of keys""" - if not prefix: - return None, 0, [repr(k) for k in keys - if isinstance(k, (string_types, bytes))] - quote_match = re.search('["\']', prefix) - quote = quote_match.group() - try: - prefix_str = eval(prefix + quote, {}) - except Exception: - return None, 0, [] - - pattern = '[^' + ''.join('\\' + c for c in delims) + ']*$' - token_match = re.search(pattern, prefix, re.UNICODE) - token_start = token_match.start() - token_prefix = token_match.group() - - # TODO: support bytes in Py3k - matched = [] - for key in 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 rem_repr.startswith('u') and prefix[0] not in 'uU': - # Found key is unicode, but prefix is Py2 string. - # Therefore attempt to interpret key as string. - try: - rem_repr = repr(rem.encode('ascii') + '"') - except UnicodeEncodeError: - continue - - 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 _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), class_name))) - - -def back_unicode_name_matches(text): - u"""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 ... - - Used on Python 3 only. - """ - if len(text)<2: - return u'', () - maybe_slash = text[-2] - if maybe_slash != '\\': - return u'', () - - 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 u'', () - try : - unic = unicodedata.name(char) - return '\\'+char,['\\'+unic] + + +def match_dict_keys(keys, prefix, delims): + """Used by dict_key_matches, matching the prefix to a list of keys""" + if not prefix: + return None, 0, [repr(k) for k in keys + if isinstance(k, (string_types, bytes))] + quote_match = re.search('["\']', prefix) + quote = quote_match.group() + try: + prefix_str = eval(prefix + quote, {}) + except Exception: + return None, 0, [] + + pattern = '[^' + ''.join('\\' + c for c in delims) + ']*$' + token_match = re.search(pattern, prefix, re.UNICODE) + token_start = token_match.start() + token_prefix = token_match.group() + + # TODO: support bytes in Py3k + matched = [] + for key in 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 rem_repr.startswith('u') and prefix[0] not in 'uU': + # Found key is unicode, but prefix is Py2 string. + # Therefore attempt to interpret key as string. + try: + rem_repr = repr(rem.encode('ascii') + '"') + except UnicodeEncodeError: + continue + + 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 _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), class_name))) + + +def back_unicode_name_matches(text): + u"""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 ... + + Used on Python 3 only. + """ + if len(text)<2: + return u'', () + maybe_slash = text[-2] + if maybe_slash != '\\': + return u'', () + + 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 u'', () + try : + unic = unicodedata.name(char) + return '\\'+char,['\\'+unic] except KeyError: - pass - return u'', () - -def back_latex_name_matches(text): - u"""Match latex characters back to unicode name - - This does ->\\sqrt - - Used on Python 3 only. - """ - if len(text)<2: - return u'', () - maybe_slash = text[-2] - if maybe_slash != '\\': - return u'', () - - - 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 u'', () - try : - latex = reverse_latex_symbol[char] - # '\\' replace the \ as well - return '\\'+char,[latex] + pass + return u'', () + +def back_latex_name_matches(text): + u"""Match latex characters back to unicode name + + This does ->\\sqrt + + Used on Python 3 only. + """ + if len(text)<2: + return u'', () + maybe_slash = text[-2] + if maybe_slash != '\\': + return u'', () + + + 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 u'', () + try : + latex = reverse_latex_symbol[char] + # '\\' replace the \ as well + return '\\'+char,[latex] except KeyError: - pass - return u'', () - - -class IPCompleter(Completer): - """Extension of the completer class with IPython-specific features""" + pass + return u'', () + + +class IPCompleter(Completer): + """Extension of the completer class with IPython-specific features""" @observe('greedy') def _greedy_changed(self, change): - """update the splitter and readline delims when greedy is changed""" + """update the splitter and readline delims when greedy is changed""" if change['new']: - self.splitter.delims = GREEDY_DELIMS - else: - self.splitter.delims = DELIMS - - if self.readline: - self.readline.set_completer_delims(self.splitter.delims) - + self.splitter.delims = GREEDY_DELIMS + else: + self.splitter.delims = DELIMS + + if self.readline: + self.readline.set_completer_delims(self.splitter.delims) + 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. - """ + 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.``. - - 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. - """ + help="""Instruct the completer to omit private method names + + Specifically, when completing on ``object.``. + + 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.``. - - When True: only those names in obj.__all__ will be included. - - When False [default]: the __all__ attribute is ignored + Specifically, when completing on ``object.``. + + When True: only those names in obj.__all__ will be included. + + When False [default]: the __all__ attribute is ignored """, ).tag(config=True) - + @observe('limit_to__all__') def _limit_to_all_changed(self, change): warnings.warn('`IPython.core.IPCompleter.limit_to__all__` configuration ' @@ -556,352 +556,352 @@ class IPCompleter(Completer): 'no effects and then removed in future version of IPython.', UserWarning) - def __init__(self, shell=None, namespace=None, global_namespace=None, - use_readline=True, config=None, **kwargs): - """IPCompleter() -> completer - - Return a completer object suitable for use by the readline library - via readline.set_completer(). - - Inputs: - - - 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: an optional dict where completions are performed. - - - global_namespace: secondary optional dict for completions, to - handle cases (such as IPython embedded inside functions) where - both Python scopes are visible. - - use_readline : bool, optional - If true, use the readline library. This completer can still function - without readline, though in that case callers must provide some extra - information on each call about the current line.""" - - self.magic_escape = ESC_MAGIC - self.splitter = CompletionSplitter() - - # Readline configuration, only used by the rlcompleter method. - if use_readline: - # We store the right version of readline so that later code - import IPython.utils.rlineimpl as readline - self.readline = readline - else: - self.readline = None - - # _greedy_changed() depends on splitter and readline being defined: - Completer.__init__(self, 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*.*)') - - # All active matcher routines for completion + def __init__(self, shell=None, namespace=None, global_namespace=None, + use_readline=True, config=None, **kwargs): + """IPCompleter() -> completer + + Return a completer object suitable for use by the readline library + via readline.set_completer(). + + Inputs: + + - 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: an optional dict where completions are performed. + + - global_namespace: secondary optional dict for completions, to + handle cases (such as IPython embedded inside functions) where + both Python scopes are visible. + + use_readline : bool, optional + If true, use the readline library. This completer can still function + without readline, though in that case callers must provide some extra + information on each call about the current line.""" + + self.magic_escape = ESC_MAGIC + self.splitter = CompletionSplitter() + + # Readline configuration, only used by the rlcompleter method. + if use_readline: + # We store the right version of readline so that later code + import IPython.utils.rlineimpl as readline + self.readline = readline + else: + self.readline = None + + # _greedy_changed() depends on splitter and readline being defined: + Completer.__init__(self, 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*.*)') + + # All active matcher routines for completion self.matchers = [ self.python_matches, - self.file_matches, - self.magic_matches, - self.python_func_kw_matches, - self.dict_key_matches, - ] - + self.file_matches, + self.magic_matches, + self.python_func_kw_matches, + self.dict_key_matches, + ] + # This is set externally by InteractiveShell self.custom_completers = None - def all_completions(self, text): - """ + def all_completions(self, text): + """ Wrapper around the complete method for the benefit of emacs. - """ - return self.complete(text)[1] - + """ + return self.complete(text)[1] + def _clean_glob(self, text): - return self.glob("%s*" % text) - - def _clean_glob_win32(self,text): - return [f.replace("\\","/") - for f in self.glob("%s*" % text)] - - def file_matches(self, text): - """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:] + return self.glob("%s*" % text) + + def _clean_glob_win32(self,text): + return [f.replace("\\","/") + for f in self.glob("%s*" % text)] + + def file_matches(self, text): + """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: + 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 == "": + + 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 + cast_unicode_py2(protect_filename(f)) for f in self.glob("*")] - - # Compute the matches from the filesystem + + # 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 at all (and we _shouldn't_, as it - # would cause bugs when the filesystem call is made). - matches = m0 - else: - matches = [text_prefix + - protect_filename(f) for f in m0] - - # Mark directories in input list by appending '/' to their names. + + 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 at all (and we _shouldn't_, as it + # would cause bugs when the filesystem call is made). + matches = m0 + else: + matches = [text_prefix + + protect_filename(f) for f in m0] + + # Mark directories in input list by appending '/' to their names. return [cast_unicode_py2(x+'/') if os.path.isdir(x) else x for x in matches] - - def magic_matches(self, text): - """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 - - # 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 - bare_text = text.lstrip(pre) - comp = [ pre2+m for m in cell_magics if m.startswith(bare_text)] - if not text.startswith(pre2): - comp += [ pre+m for m in line_magics if m.startswith(bare_text)] + + def magic_matches(self, text): + """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 + + # 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 + bare_text = text.lstrip(pre) + comp = [ pre2+m for m in cell_magics if m.startswith(bare_text)] + if not text.startswith(pre2): + comp += [ pre+m for m in line_magics if m.startswith(bare_text)] return [cast_unicode_py2(c) for c in comp] - + def python_matches(self, text): - """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 . - 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 embededsignature=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__', '')) - - if PY3: - _keeps = (inspect.Parameter.KEYWORD_ONLY, - inspect.Parameter.POSITIONAL_OR_KEYWORD) - signature = inspect.signature - else: - import IPython.utils.signatures - _keeps = (IPython.utils.signatures.Parameter.KEYWORD_ONLY, - IPython.utils.signatures.Parameter.POSITIONAL_OR_KEYWORD) - signature = IPython.utils.signatures.signature - - try: - sig = signature(call_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''' - '.*?(?,a=1)", the candidate is "foo" - tokens = regexp.findall(self.text_until_cursor) - tokens.reverse() - iterTokens = iter(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 - # lookup the candidate callable matches either using global_matches - # or attr_matches for dotted names - if len(ids) == 1: - callableMatches = self.global_matches(ids[0]) - else: - callableMatches = self.attr_matches('.'.join(ids[::-1])) - argMatches = [] - for callableMatch in callableMatches: - try: - namedArgs = self._default_arguments(eval(callableMatch, - self.namespace)) - except: - continue - - for namedArg in namedArgs: - if namedArg.startswith(text): + """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 . + 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 embededsignature=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__', '')) + + if PY3: + _keeps = (inspect.Parameter.KEYWORD_ONLY, + inspect.Parameter.POSITIONAL_OR_KEYWORD) + signature = inspect.signature + else: + import IPython.utils.signatures + _keeps = (IPython.utils.signatures.Parameter.KEYWORD_ONLY, + IPython.utils.signatures.Parameter.POSITIONAL_OR_KEYWORD) + signature = IPython.utils.signatures.signature + + try: + sig = signature(call_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''' + '.*?(?,a=1)", the candidate is "foo" + tokens = regexp.findall(self.text_until_cursor) + tokens.reverse() + iterTokens = iter(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 + # lookup the candidate callable matches either using global_matches + # or attr_matches for dotted names + if len(ids) == 1: + callableMatches = self.global_matches(ids[0]) + else: + callableMatches = self.attr_matches('.'.join(ids[::-1])) + argMatches = [] + for callableMatch in callableMatches: + try: + namedArgs = self._default_arguments(eval(callableMatch, + self.namespace)) + except: + continue + + for namedArg in namedArgs: + if namedArg.startswith(text): argMatches.append(u"%s=" %namedArg) - return argMatches - - def dict_key_matches(self, text): - "Match string keys in a dictionary, after e.g. 'foo[' " - def get_keys(obj): + return argMatches + + def dict_key_matches(self, text): + "Match string keys in a dictionary, after e.g. 'foo[' " + def get_keys(obj): # Objects can define their own completions by defining an # _ipy_key_completions_() method. method = get_real_method(obj, '_ipython_key_completions_') @@ -909,289 +909,289 @@ class IPCompleter(Completer): 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 [] - - try: - regexps = self.__dict_key_regexps - except AttributeError: - dict_key_re_fmt = r'''(?x) - ( # match dict-referring expression wrt greedy setting - %s - ) - \[ # open bracket - \s* # and optional whitespace - ([uUbB]? # string prefix (r not handled) - (?: # unclosed string - '(?:[^']|(? 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] - - def unicode_name_matches(self, text): - u"""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. - - Used on Python 3 only. - """ - 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] + 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 [] + + try: + regexps = self.__dict_key_regexps + except AttributeError: + dict_key_re_fmt = r'''(?x) + ( # match dict-referring expression wrt greedy setting + %s + ) + \[ # open bracket + \s* # and optional whitespace + ([uUbB]? # string prefix (r not handled) + (?: # unclosed string + '(?:[^']|(? 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] + + def unicode_name_matches(self, text): + u"""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. + + Used on Python 3 only. + """ + 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 u'', [] - - - - - def latex_matches(self, text): - u"""Match Latex syntax for unicode characters. - - This does both \\alp -> \\alpha and \\alpha -> α - - Used on Python 3 only. - """ - 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)] - return s, matches - return u'', [] - - def dispatch_custom_completer(self, text): + pass + return u'', [] + + + + + def latex_matches(self, text): + u"""Match Latex syntax for unicode characters. + + This does both \\alp -> \\alpha and \\alpha -> α + + Used on Python 3 only. + """ + 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)] + return s, matches + return u'', [] + + 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 = Bunch() - 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 + 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 = Bunch() + 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 = [cast_unicode_py2(r) for r in res if r.startswith(text)] - if withcase: - return withcase - # if none, then case insensitive ones are ok too - text_low = text.lower() + if withcase: + return withcase + # if none, then case insensitive ones are ok too + text_low = text.lower() return [cast_unicode_py2(r) for r in res if r.lower().startswith(text_low)] - except TryNext: - pass + except TryNext: + pass except KeyboardInterrupt: """ If custom completer take too long, let keyboard interrupt abort and return nothing. """ break - - return None - - def complete(self, text=None, line_buffer=None, cursor_pos=None): - """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 - ------- - text : str - Text that was actually used in the completion. - - matches : list - A list of completion matches. - """ - # 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) - + + return None + + def complete(self, text=None, line_buffer=None, cursor_pos=None): + """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 + ------- + text : str + Text that was actually used in the completion. + + matches : list + A list of completion matches. + """ + # 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 PY3 and self.backslash_combining_completions: - base_text = text if not line_buffer else line_buffer[:cursor_pos] - latex_text, latex_matches = self.latex_matches(base_text) - if latex_matches: + base_text = text if not line_buffer else line_buffer[:cursor_pos] + latex_text, latex_matches = self.latex_matches(base_text) + if latex_matches: return latex_text, latex_matches - name_text = '' - name_matches = [] - for meth in (self.unicode_name_matches, back_latex_name_matches, back_unicode_name_matches): - name_text, name_matches = meth(base_text) - if name_text: + name_text = '' + name_matches = [] + for meth in (self.unicode_name_matches, back_latex_name_matches, back_unicode_name_matches): + name_text, name_matches = meth(base_text) + if name_text: return name_text, name_matches[:MATCHES_LIMIT] - - # if text is either None or an empty string, rely on the line buffer - if not text: - text = self.splitter.split_line(line_buffer, cursor_pos) - - # 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] - - # Start with a clean slate of completions - self.matches[:] = [] - custom_res = self.dispatch_custom_completer(text) - if custom_res is not None: - # did custom completers produce something? - self.matches = custom_res - else: - # Extend the list of completions with the results of each - # matcher, so we return results to the user from all - # namespaces. - if self.merge_completions: - self.matches = [] - for matcher in self.matchers: - try: - self.matches.extend(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: - self.matches = matcher(text) - if self.matches: - break - # 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 evironments. + + # if text is either None or an empty string, rely on the line buffer + if not text: + text = self.splitter.split_line(line_buffer, cursor_pos) + + # 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] + + # Start with a clean slate of completions + self.matches[:] = [] + custom_res = self.dispatch_custom_completer(text) + if custom_res is not None: + # did custom completers produce something? + self.matches = custom_res + else: + # Extend the list of completions with the results of each + # matcher, so we return results to the user from all + # namespaces. + if self.merge_completions: + self.matches = [] + for matcher in self.matchers: + try: + self.matches.extend(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: + self.matches = matcher(text) + if self.matches: + break + # 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 evironments. self.matches = sorted(set(self.matches), key=completions_sorting_key)[:MATCHES_LIMIT] - - return text, self.matches + + return text, self.matches diff --git a/contrib/python/ipython/py2/IPython/core/completerlib.py b/contrib/python/ipython/py2/IPython/core/completerlib.py index e736ca73d10..4e7ae419412 100644 --- a/contrib/python/ipython/py2/IPython/core/completerlib.py +++ b/contrib/python/ipython/py2/IPython/core/completerlib.py @@ -1,76 +1,76 @@ -# 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 -#----------------------------------------------------------------------------- -from __future__ import print_function - -# Stdlib imports -import glob -import inspect +# 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 +#----------------------------------------------------------------------------- +from __future__ import print_function + +# Stdlib imports +import glob +import inspect import itertools -import os -import re -import sys - -try: - # Python >= 3.3 - from importlib.machinery import all_suffixes - _suffixes = all_suffixes() -except ImportError: - from imp import get_suffixes - _suffixes = [ s[0] for s in get_suffixes() ] - -# Third-party imports -from time import time -from zipimport import zipimporter - -# Our own imports -from IPython.core.completer import expand_user, compress_user -from IPython.core.error import TryNext -from IPython.utils._process_common import arg_split -from IPython.utils.py3compat import string_types - -# FIXME: this should be pulled in with the right call via the component system -from IPython import get_ipython - +import os +import re +import sys + +try: + # Python >= 3.3 + from importlib.machinery import all_suffixes + _suffixes = all_suffixes() +except ImportError: + from imp import get_suffixes + _suffixes = [ s[0] for s in get_suffixes() ] + +# Third-party imports +from time import time +from zipimport import zipimporter + +# Our own imports +from IPython.core.completer import expand_user, compress_user +from IPython.core.error import TryNext +from IPython.utils._process_common import arg_split +from IPython.utils.py3compat import string_types + +# FIXME: this should be pulled in with the right call via the component system +from IPython import get_ipython + from __res import importer -#----------------------------------------------------------------------------- -# Globals and constants -#----------------------------------------------------------------------------- - -# 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[a-zA-Z_][a-zA-Z0-9_]*?)' - r'(?P[/\\]__init__)?' - r'(?P%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 -#----------------------------------------------------------------------------- - +#----------------------------------------------------------------------------- +# Globals and constants +#----------------------------------------------------------------------------- + +# 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[a-zA-Z_][a-zA-Z0-9_]*?)' + r'(?P[/\\]__init__)?' + r'(?P%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 @@ -116,291 +116,291 @@ def arcadia_get_root_modules(): -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() +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_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 try_import(mod, only_modules=False): + 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 try_import(mod, only_modules=False): mod = mod.rstrip('.') - try: - m = __import__(mod) - except: - return [] - mods = mod.split('.') - for module in mods[1:]: - m = getattr(m, module) - + try: + m = __import__(mod) + except: + return [] + mods = mod.split('.') + for module in mods[1:]: + m = getattr(m, module) + 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)]) - - completions.extend(getattr(m, '__all__', [])) - if m_is_init: + + 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)]) + + completions.extend(getattr(m, '__all__', [])) + if m_is_init: completions.extend(arcadia_module_list(mod)) completions = {c for c in completions if isinstance(c, string_types)} completions.discard('__init__') return sorted(completions) - - -#----------------------------------------------------------------------------- -# Completion-related functions. -#----------------------------------------------------------------------------- - -def quick_completer(cmd, completions): - """ 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 - bar baz - [d:\ipython]|3> foo ba - """ - - if isinstance(completions, string_types): - 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 -> 'import ' - if nwords == 3 and words[0] == 'from': - return ['import '] - - # 'from xy' or 'import xy' - if nwords < 3 and (words[0] in {'%aimport', 'import', 'from'}) : - if nwords == 1: + + +#----------------------------------------------------------------------------- +# Completion-related functions. +#----------------------------------------------------------------------------- + +def quick_completer(cmd, completions): + """ 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 + bar baz + [d:\ipython]|3> foo ba + """ + + if isinstance(completions, string_types): + 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 -> 'import ' + if nwords == 3 and words[0] == 'from': + return ['import '] + + # 'from xy' or 'import xy' + 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: + 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' - 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() + completion_list = try_import('.'.join(mod[:-1]), True) + return ['.'.join(mod[:-1] + [el]) for el in completion_list] + + # 'from xyz import abc' + 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/py2/IPython/core/crashhandler.py b/contrib/python/ipython/py2/IPython/core/crashhandler.py index 22bbd7ae815..8341a61db8c 100644 --- a/contrib/python/ipython/py2/IPython/core/crashhandler.py +++ b/contrib/python/ipython/py2/IPython/core/crashhandler.py @@ -1,59 +1,59 @@ -# 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. -# 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 __future__ import print_function - -import os -import sys -import traceback -from pprint import pformat - -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, getcwd - -#----------------------------------------------------------------------------- -# 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} - +# 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. +# 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 __future__ import print_function + +import os +import sys +import traceback +from pprint import pformat + +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, getcwd + +#----------------------------------------------------------------------------- +# 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, @@ -64,163 +64,163 @@ In your email, please also include information about: 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 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=None, contact_email=None, - bug_tracker=None, show_crash_traceback=True, call_pdb=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 - - Non-argument instance 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 = getcwd() - if rptdir is None or not os.path.isdir(rptdir): - rptdir = getcwd() - report_name = os.path.join(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') - except: - print('Could not create crash report on disk.', file=sys.stderr) - return - - # 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)) - report.close() - input("Hit 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), file=sys.stderr) - +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 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=None, contact_email=None, + bug_tracker=None, show_crash_traceback=True, call_pdb=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 + + Non-argument instance 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 = getcwd() + if rptdir is None or not os.path.isdir(rptdir): + rptdir = getcwd() + report_name = os.path.join(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') + except: + print('Could not create crash report on disk.', file=sys.stderr) + return + + # 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)) + report.close() + input("Hit 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), file=sys.stderr) + diff --git a/contrib/python/ipython/py2/IPython/core/debugger.py b/contrib/python/ipython/py2/IPython/core/debugger.py index f08cfb1a789..c5a443eb5bc 100644 --- a/contrib/python/ipython/py2/IPython/core/debugger.py +++ b/contrib/python/ipython/py2/IPython/core/debugger.py @@ -1,53 +1,53 @@ -# -*- coding: utf-8 -*- -""" -Pdb debugger class. - -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 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: - +# -*- coding: utf-8 -*- +""" +Pdb debugger class. + +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 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 """ - -#***************************************************************************** -# -# This file is licensed under the PSF license. -# -# Copyright (C) 2001 Python Software Foundation, www.python.org -# Copyright (C) 2005-2006 Fernando Perez. -# -# -#***************************************************************************** -from __future__ import print_function - -import bdb -import functools -import inspect -import sys + +#***************************************************************************** +# +# This file is licensed under the PSF license. +# +# Copyright (C) 2001 Python Software Foundation, www.python.org +# Copyright (C) 2005-2006 Fernando Perez. +# +# +#***************************************************************************** +from __future__ import print_function + +import bdb +import functools +import inspect +import sys import warnings - -from IPython import get_ipython -from IPython.utils import PyColorize, ulinecache + +from IPython import get_ipython +from IPython.utils import PyColorize, ulinecache from IPython.utils import coloransi, py3compat -from IPython.core.excolors import exception_colors -from IPython.testing.skipdoctest import skip_doctest - +from IPython.core.excolors import exception_colors +from IPython.testing.skipdoctest import skip_doctest + -prompt = 'ipdb> ' +prompt = 'ipdb> ' -#We have to check this directly from sys.argv, config struct not yet available +#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. + +# Allow the set_trace code to operate outside of an ipython instance, even if +# it does so with some limitations. The rest of this support is implemented in +# the Tracer constructor. def make_arrow(pad): """generate the leading arrow in front of traceback or debugger""" @@ -58,555 +58,555 @@ def make_arrow(pad): return '' -def BdbQuit_excepthook(et, ev, tb, excepthook=None): - """Exception hook which handles `BdbQuit` exceptions. - - All other exceptions are processed using the `excepthook` - parameter. - """ +def BdbQuit_excepthook(et, ev, tb, excepthook=None): + """Exception hook which handles `BdbQuit` exceptions. + + All other exceptions are processed using the `excepthook` + parameter. + """ warnings.warn("`BdbQuit_excepthook` is deprecated since version 5.1", DeprecationWarning, stacklevel=2) - if et==bdb.BdbQuit: - print('Exiting Debugger.') - elif excepthook is not None: - excepthook(et, ev, tb) - else: - # Backwards compatibility. Raise deprecation warning? - BdbQuit_excepthook.excepthook_ori(et,ev,tb) - - -def BdbQuit_IPython_excepthook(self,et,ev,tb,tb_offset=None): + if et==bdb.BdbQuit: + print('Exiting Debugger.') + elif excepthook is not None: + excepthook(et, ev, tb) + else: + # Backwards compatibility. Raise deprecation warning? + BdbQuit_excepthook.excepthook_ori(et,ev,tb) + + +def BdbQuit_IPython_excepthook(self,et,ev,tb,tb_offset=None): warnings.warn( "`BdbQuit_IPython_excepthook` is deprecated since version 5.1", DeprecationWarning, stacklevel=2) - print('Exiting Debugger.') - - -class Tracer(object): + print('Exiting Debugger.') + + +class Tracer(object): """ DEPRECATED - + Class for local debugging, similar to pdb.set_trace. - Instances of this class, when called, behave like pdb.set_trace, but - providing IPython's enhanced capabilities. - - This is implemented as a class which must be initialized in your own code - and not as a standalone function because we need to detect at runtime - whether IPython is already active or not. That detection is done in the - constructor, ensuring that this code plays nicely with a running IPython, - while functioning acceptably (though with limitations) if outside of it. - """ - - @skip_doctest - def __init__(self, colors=None): + Instances of this class, when called, behave like pdb.set_trace, but + providing IPython's enhanced capabilities. + + This is implemented as a class which must be initialized in your own code + and not as a standalone function because we need to detect at runtime + whether IPython is already active or not. That detection is done in the + constructor, ensuring that this code plays nicely with a running IPython, + while functioning acceptably (though with limitations) if outside of it. + """ + + @skip_doctest + def __init__(self, colors=None): """ DEPRECATED - + Create a local debugger instance. - Parameters - ---------- - - colors : str, optional - The name of the color scheme to use, it must be one of IPython's - valid color schemes. If not given, the function will default to - the current IPython scheme when running inside IPython, and to - 'NoColor' otherwise. - - Examples - -------- - :: - - from IPython.core.debugger import Tracer; debug_here = Tracer() - - Later in your code:: - - debug_here() # -> will open up the debugger at that point. - - Once the debugger activates, you can use all of its regular commands to - step through code, set breakpoints, etc. See the pdb documentation - from the Python standard library for usage details. - """ + Parameters + ---------- + + colors : str, optional + The name of the color scheme to use, it must be one of IPython's + valid color schemes. If not given, the function will default to + the current IPython scheme when running inside IPython, and to + 'NoColor' otherwise. + + Examples + -------- + :: + + from IPython.core.debugger import Tracer; debug_here = Tracer() + + Later in your code:: + + debug_here() # -> will open up the debugger at that point. + + Once the debugger activates, you can use all of its regular commands to + step through code, set breakpoints, etc. See the pdb documentation + from the Python standard library for usage details. + """ warnings.warn("`Tracer` is deprecated since version 5.1, directly use " "`IPython.core.debugger.Pdb.set_trace()`", DeprecationWarning, stacklevel=2) - - ip = get_ipython() - if ip is None: - # Outside of ipython, we set our own exception hook manually - sys.excepthook = functools.partial(BdbQuit_excepthook, - excepthook=sys.excepthook) - def_colors = 'NoColor' - else: - # In ipython, we use its custom exception handler mechanism - def_colors = ip.colors - ip.set_custom_exc((bdb.BdbQuit,), BdbQuit_IPython_excepthook) - - if colors is None: - colors = def_colors - - # The stdlib debugger internally uses a modified repr from the `repr` - # module, that limits the length of printed strings to a hardcoded - # limit of 30 characters. That much trimming is too aggressive, let's - # at least raise that limit to 80 chars, which should be enough for - # most interactive uses. - try: - try: - from reprlib import aRepr # Py 3 - except ImportError: - from repr import aRepr # Py 2 - aRepr.maxstring = 80 - except: - # This is only a user-facing convenience, so any error we encounter - # here can be warned about but can be otherwise ignored. These - # printouts will tell us about problems if this API changes - import traceback - traceback.print_exc() - - self.debugger = Pdb(colors) - - def __call__(self): - """Starts an interactive debugger at the point where called. - - This is similar to the pdb.set_trace() function from the std lib, but - using IPython's enhanced debugger.""" - - self.debugger.set_trace(sys._getframe().f_back) - - -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__ = old_fn.__doc__ + additional_text - return wrapper - - -def _file_lines(fname): - """Return the contents of a named file as a list of lines. - - This function never raises an IOError exception: if the file can't be - read, it simply returns an empty list.""" - - try: - outfile = open(fname) - except IOError: - return [] - else: - out = outfile.readlines() - outfile.close() - return out - - + + ip = get_ipython() + if ip is None: + # Outside of ipython, we set our own exception hook manually + sys.excepthook = functools.partial(BdbQuit_excepthook, + excepthook=sys.excepthook) + def_colors = 'NoColor' + else: + # In ipython, we use its custom exception handler mechanism + def_colors = ip.colors + ip.set_custom_exc((bdb.BdbQuit,), BdbQuit_IPython_excepthook) + + if colors is None: + colors = def_colors + + # The stdlib debugger internally uses a modified repr from the `repr` + # module, that limits the length of printed strings to a hardcoded + # limit of 30 characters. That much trimming is too aggressive, let's + # at least raise that limit to 80 chars, which should be enough for + # most interactive uses. + try: + try: + from reprlib import aRepr # Py 3 + except ImportError: + from repr import aRepr # Py 2 + aRepr.maxstring = 80 + except: + # This is only a user-facing convenience, so any error we encounter + # here can be warned about but can be otherwise ignored. These + # printouts will tell us about problems if this API changes + import traceback + traceback.print_exc() + + self.debugger = Pdb(colors) + + def __call__(self): + """Starts an interactive debugger at the point where called. + + This is similar to the pdb.set_trace() function from the std lib, but + using IPython's enhanced debugger.""" + + self.debugger.set_trace(sys._getframe().f_back) + + +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__ = old_fn.__doc__ + additional_text + return wrapper + + +def _file_lines(fname): + """Return the contents of a named file as a list of lines. + + This function never raises an IOError exception: if the file can't be + read, it simply returns an empty list.""" + + try: + outfile = open(fname) + except IOError: + return [] + else: + out = outfile.readlines() + outfile.close() + return out + + class Pdb(OldPdb): """Modified Pdb class, does not load readline. - + for a standalone version that uses prompt_toolkit, see `IPython.terminal.debugger.TerminalPdb` and `IPython.terminal.debugger.set_trace()` """ def __init__(self, color_scheme=None, completekey=None, - stdin=None, stdout=None, context=5): - - # Parent constructor: - try: + stdin=None, stdout=None, context=5): + + # Parent constructor: + try: self.context = int(context) - if self.context <= 0: - raise ValueError("Context must be a positive integer") - except (TypeError, ValueError): - raise ValueError("Context must be a positive integer") - + if self.context <= 0: + raise ValueError("Context must be a positive integer") + except (TypeError, ValueError): + raise ValueError("Context must be a positive integer") + OldPdb.__init__(self, completekey, stdin, stdout) - - # IPython changes... - self.shell = get_ipython() - - if self.shell is None: + + # 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() + # 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 - + if color_scheme is not None: warnings.warn( "The `color_scheme` argument is deprecated since version 5.1", DeprecationWarning) else: color_scheme = self.shell.colors - - self.aliases = {} - - # 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 - + + 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 - self.set_colors(color_scheme) - - # Add a python parser so we can syntax highlight source while - # debugging. - self.parser = PyColorize.Parser() - + self.set_colors(color_scheme) + + # Add a python parser so we can syntax highlight source while + # debugging. + self.parser = PyColorize.Parser() + # Set the prompt - the default prompt is '(Pdb)' self.prompt = prompt - - def set_colors(self, scheme): - """Shorthand access to the color table scheme selector method.""" - self.color_scheme_table.set_active_scheme(scheme) - - def interaction(self, frame, traceback): + + def set_colors(self, scheme): + """Shorthand access to the color table scheme selector method.""" + self.color_scheme_table.set_active_scheme(scheme) + + def interaction(self, frame, traceback): try: OldPdb.interaction(self, frame, traceback) except KeyboardInterrupt: sys.stdout.write('\n' + self.shell.get_exception_only()) - - def new_do_up(self, arg): - OldPdb.do_up(self, arg) - do_u = do_up = decorate_fn_with_doc(new_do_up, OldPdb.do_up) - - def new_do_down(self, arg): - OldPdb.do_down(self, arg) - - do_d = do_down = decorate_fn_with_doc(new_do_down, OldPdb.do_down) - - 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): - 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): - raise ValueError("Context must be a positive integer") - try: - for frame_lineno in self.stack: - self.print_stack_entry(frame_lineno, context=context) - except KeyboardInterrupt: - pass - + + def new_do_up(self, arg): + OldPdb.do_up(self, arg) + do_u = do_up = decorate_fn_with_doc(new_do_up, OldPdb.do_up) + + def new_do_down(self, arg): + OldPdb.do_down(self, arg) + + do_d = do_down = decorate_fn_with_doc(new_do_down, OldPdb.do_down) + + 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): + 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): + raise ValueError("Context must be a positive integer") + try: + for frame_lineno in self.stack: + self.print_stack_entry(frame_lineno, context=context) + 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): - raise ValueError("Context must be a positive integer") + 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): + raise ValueError("Context must be a positive integer") print(self.format_stack_entry(frame_lineno, '', context)) - - # vds: >> - frame, lineno = frame_lineno - filename = frame.f_code.co_filename - self.shell.hooks.synchronize_with_editor(filename, lineno, 0) - # vds: << - - 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") - except (TypeError, ValueError): - print("Context must be a positive integer") - try: - import reprlib # Py 3 - except ImportError: - import repr as reprlib # Py 2 - - ret = [] - - Colors = self.color_scheme_table.active_colors - ColorsNormal = Colors.Normal - tpl_link = u'%s%%s%s' % (Colors.filenameEm, ColorsNormal) - tpl_call = u'%s%%s%s%%s%s' % (Colors.vName, Colors.valEm, ColorsNormal) - tpl_line = u'%%s%s%%s %s%%s' % (Colors.lineno, ColorsNormal) - tpl_line_em = u'%%s%s%%s %s%%s%s' % (Colors.linenoEm, Colors.line, - ColorsNormal) - - frame, lineno = frame_lineno - - return_value = '' - if '__return__' in frame.f_locals: - rv = frame.f_locals['__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 = "" - - call = '' - if func != '?': - if '__args__' in frame.f_locals: - args = reprlib.repr(frame.f_locals['__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(u'%s(%s)%s\n' % (link,lineno,call)) - - start = lineno - 1 - context//2 - lines = ulinecache.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 = "" - - scheme = self.color_scheme_table.active_scheme_name - new_line, err = self.parser.format2(line, 'str', scheme) - 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) + + # vds: >> + frame, lineno = frame_lineno + filename = frame.f_code.co_filename + self.shell.hooks.synchronize_with_editor(filename, lineno, 0) + # vds: << + + 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") + except (TypeError, ValueError): + print("Context must be a positive integer") + try: + import reprlib # Py 3 + except ImportError: + import repr as reprlib # Py 2 + + ret = [] + + Colors = self.color_scheme_table.active_colors + ColorsNormal = Colors.Normal + tpl_link = u'%s%%s%s' % (Colors.filenameEm, ColorsNormal) + tpl_call = u'%s%%s%s%%s%s' % (Colors.vName, Colors.valEm, ColorsNormal) + tpl_line = u'%%s%s%%s %s%%s' % (Colors.lineno, ColorsNormal) + tpl_line_em = u'%%s%s%%s %s%%s%s' % (Colors.linenoEm, Colors.line, + ColorsNormal) + + frame, lineno = frame_lineno + + return_value = '' + if '__return__' in frame.f_locals: + rv = frame.f_locals['__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 = "" + + call = '' + if func != '?': + if '__args__' in frame.f_locals: + args = reprlib.repr(frame.f_locals['__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(u'%s(%s)%s\n' % (link,lineno,call)) + + start = lineno - 1 - context//2 + lines = ulinecache.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 = "" + + scheme = self.color_scheme_table.active_scheme_name + new_line, err = self.parser.format2(line, 'str', scheme) + 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)) - + 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 == "" and hasattr(self, "_exec_filename"): - filename = self._exec_filename - - for lineno in range(first, last+1): - line = ulinecache.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 - + + + 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 == "" and hasattr(self, "_exec_filename"): + filename = self._exec_filename + + for lineno in range(first, last+1): + line = ulinecache.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)) - - except KeyboardInterrupt: - pass - - def do_list(self, arg): + + except KeyboardInterrupt: + pass + + 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)) - 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 obj.f_locals: - # 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): + 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)) + 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 obj.f_locals: + # 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_pdef(self, arg): - """Print the call signature for any callable object. - - The debugger interface to %pdef""" - namespaces = [('Locals', self.curframe.f_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.f_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.f_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.f_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.f_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.f_locals), - ('Globals', self.curframe.f_globals)] - self.shell.find_line_magic('psource')(arg, namespaces=namespaces) - - if sys.version_info > (3, ): - 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: - context = int(arg) - self.print_stack_trace(context) - else: - self.print_stack_trace() - - do_w = do_where + 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_pdef(self, arg): + """Print the call signature for any callable object. + + The debugger interface to %pdef""" + namespaces = [('Locals', self.curframe.f_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.f_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.f_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.f_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.f_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.f_locals), + ('Globals', self.curframe.f_globals)] + self.shell.find_line_magic('psource')(arg, namespaces=namespaces) + + if sys.version_info > (3, ): + 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: + context = int(arg) + self.print_stack_trace(context) + else: + self.print_stack_trace() + + do_w = do_where def set_trace(frame=None): diff --git a/contrib/python/ipython/py2/IPython/core/display.py b/contrib/python/ipython/py2/IPython/core/display.py index 5c82a57b313..2c38b329337 100644 --- a/contrib/python/ipython/py2/IPython/core/display.py +++ b/contrib/python/ipython/py2/IPython/core/display.py @@ -1,124 +1,124 @@ -# -*- 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 __future__ import print_function - +# -*- 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 __future__ import print_function + try: from base64 import encodebytes as base64_encode except ImportError: from base64 import encodestring as base64_encode from binascii import b2a_hex, hexlify -import json -import mimetypes -import os -import struct +import json +import mimetypes +import os +import struct import sys -import warnings - -from IPython.utils.py3compat import (string_types, cast_bytes_py2, cast_unicode, - unicode_type) -from IPython.testing.skipdoctest import skip_doctest - -__all__ = ['display', 'display_pretty', 'display_html', 'display_markdown', -'display_svg', 'display_png', 'display_jpeg', 'display_latex', 'display_json', -'display_javascript', 'display_pdf', 'DisplayObject', 'TextDisplayObject', +import warnings + +from IPython.utils.py3compat import (string_types, cast_bytes_py2, cast_unicode, + unicode_type) +from IPython.testing.skipdoctest import skip_doctest + +__all__ = ['display', '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', 'Javascript', -'Image', 'clear_output', 'set_matplotlib_formats', 'set_matplotlib_close', +'Image', 'clear_output', 'set_matplotlib_formats', 'set_matplotlib_close', 'publish_display_data', 'update_display', 'DisplayHandle'] - -#----------------------------------------------------------------------------- -# 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 _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 - -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 : tuple of objects - 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(*objs, raw=raw, metadata=metadata, include=[mimetype]) - -#----------------------------------------------------------------------------- -# Main functions -#----------------------------------------------------------------------------- + +#----------------------------------------------------------------------------- +# 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 _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 + +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 : tuple of objects + 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(*objs, raw=raw, metadata=metadata, include=[mimetype]) + +#----------------------------------------------------------------------------- +# Main functions +#----------------------------------------------------------------------------- # use * to indicate transient is keyword-only def publish_display_data(data, metadata=None, source=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. - - 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. mime-type keys matching those in data can be used - to specify metadata about particular representations. - source : str, deprecated - Unused. + """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. 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 + """ + from IPython.core.interactiveshell import InteractiveShell display_pub = InteractiveShell.instance().display_pub @@ -127,45 +127,45 @@ def publish_display_data(data, metadata=None, source=None, **kwargs): # TODO: We could check for ipykernel version and provide a detailed upgrade message. display_pub.publish( - data=data, - metadata=metadata, + 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, **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. - +def display(*objs, **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 : tuple of objects - 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] + Parameters + ---------- + objs : tuple of objects + 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. + 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. + 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). @@ -276,8 +276,8 @@ def display(*objs, **kwargs): from IPython.display import display - """ - from IPython.core.interactiveshell import InteractiveShell + """ + from IPython.core.interactiveshell import InteractiveShell if not InteractiveShell.initialized(): # Directly print objects. @@ -300,26 +300,26 @@ def display(*objs, **kwargs): raise TypeError('display_id required for update_display') if transient: kwargs['transient'] = transient - - if not raw: - format = InteractiveShell.instance().display_formatter.format - - for obj in objs: - if raw: + + if not raw: + format = InteractiveShell.instance().display_formatter.format + + 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) + 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, **kwargs): """Update an existing display by id @@ -395,346 +395,346 @@ class DisplayHandle(object): update_display(obj, display_id=self.display_id, **kwargs) -def display_pretty(*objs, **kwargs): - """Display the pretty (default) representation of an object. - - Parameters - ---------- - objs : tuple of objects - 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 : tuple of objects - 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 : tuple of objects - 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 : tuple of objects - 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 : tuple of objects - 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 : tuple of objects - 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 : tuple of objects - 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 : tuple of objects - 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 : tuple of objects - 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 : tuple of objects - 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 - - def __init__(self, data=None, url=None, filename=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. - """ - if data is not None and isinstance(data, string_types): - 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.data = data - self.url = url - self.filename = None if filename is None else unicode_type(filename) - - 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 reload(self): - """Reload the raw data from file or URL.""" - if self.filename is not None: - with open(self.filename, self._read_flags) as f: - self.data = f.read() - elif self.url is not None: - try: - try: - from urllib.request import urlopen # Py3 - except ImportError: - from urllib2 import urlopen - response = urlopen(self.url) - self.data = response.read() - # extract encoding from header, if there is one: - encoding = None - for sub in response.headers['content-type'].split(';'): - sub = sub.strip() - if sub.startswith('charset'): - encoding = sub.split('=')[-1].strip() - break - # decode data, if an encoding was specified - if encoding: - self.data = self.data.decode(encoding, 'replace') - except: - self.data = None - -class TextDisplayObject(DisplayObject): - """Validate that display data is text""" - def _check_data(self): - if self.data is not None and not isinstance(self.data, string_types): - raise TypeError("%s expects text, not %r" % (self.__class__.__name__, self.data)) - -class Pretty(TextDisplayObject): - +def display_pretty(*objs, **kwargs): + """Display the pretty (default) representation of an object. + + Parameters + ---------- + objs : tuple of objects + 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 : tuple of objects + 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 : tuple of objects + 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 : tuple of objects + 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 : tuple of objects + 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 : tuple of objects + 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 : tuple of objects + 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 : tuple of objects + 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 : tuple of objects + 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 : tuple of objects + 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 + + def __init__(self, data=None, url=None, filename=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. + """ + if data is not None and isinstance(data, string_types): + 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.data = data + self.url = url + self.filename = None if filename is None else unicode_type(filename) + + 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 reload(self): + """Reload the raw data from file or URL.""" + if self.filename is not None: + with open(self.filename, self._read_flags) as f: + self.data = f.read() + elif self.url is not None: + try: + try: + from urllib.request import urlopen # Py3 + except ImportError: + from urllib2 import urlopen + response = urlopen(self.url) + self.data = response.read() + # extract encoding from header, if there is one: + encoding = None + for sub in response.headers['content-type'].split(';'): + sub = sub.strip() + if sub.startswith('charset'): + encoding = sub.split('=')[-1].strip() + break + # decode data, if an encoding was specified + if encoding: + self.data = self.data.decode(encoding, 'replace') + except: + self.data = None + +class TextDisplayObject(DisplayObject): + """Validate that display data is text""" + def _check_data(self): + if self.data is not None and not isinstance(self.data, string_types): + 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 _repr_html_(self): - return self.data - - 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 - - -class Math(TextDisplayObject): - - def _repr_latex_(self): - s = self.data.strip('$') - return "$$%s$$" % s - - -class Latex(TextDisplayObject): - - def _repr_latex_(self): - return self.data - - -class SVG(DisplayObject): - + + +class HTML(TextDisplayObject): + + def _repr_html_(self): + return self.data + + 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 + + +class Math(TextDisplayObject): + + def _repr_latex_(self): + s = self.data.strip('$') + return "$$%s$$" % s + + +class Latex(TextDisplayObject): + + def _repr_latex_(self): + return self.data + + +class SVG(DisplayObject): + _read_flags = 'rb' - # wrap data in a property, which extracts the 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 - svg = cast_bytes_py2(svg) - 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 - + # wrap data in a property, which extracts the 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 + svg = cast_bytes_py2(svg) + 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 + class ProgressBar(DisplayObject): """Progressbar supports displaying a progressbar like element """ @@ -751,7 +751,7 @@ class ProgressBar(DisplayObject): 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) @@ -797,367 +797,367 @@ class ProgressBar(DisplayObject): """Python 2 compatibility""" return self.__next__() -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 _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, string_types): - warnings.warn("JSON expects JSONable dict or list, not JSON strings") - data = json.loads(data) - self._data = data - - def _repr_json_(self): - return self.data - -css_t = """$("head").append($("").attr({ - rel: "stylesheet", - type: "text/css", - href: "%s" -})); -""" - -lib_t1 = """$.getScript("%s", function () { -""" -lib_t2 = """}); -""" - -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, string_types): - lib = [lib] - elif lib is None: - lib = [] - if isinstance(css, string_types): - 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 - w4h4 = data[ihdr+4:ihdr+12] - return struct.unpack('>ii', w4h4) - -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 - -class Image(DisplayObject): - - _read_flags = 'rb' - _FMT_JPEG = u'jpeg' - _FMT_PNG = u'png' - _ACCEPTABLE_EMBEDDINGS = [_FMT_JPEG, _FMT_PNG] - - def __init__(self, data=None, url=None, filename=None, format=None, - embed=None, width=None, height=None, retina=False, - unconfined=False, metadata=None): - """Create a PNG/JPEG 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). 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 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 +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 _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, string_types): + warnings.warn("JSON expects JSONable dict or list, not JSON strings") + data = json.loads(data) + self._data = data + + def _repr_json_(self): + return self.data + +css_t = """$("head").append($("").attr({ + rel: "stylesheet", + type: "text/css", + href: "%s" +})); +""" + +lib_t1 = """$.getScript("%s", function () { +""" +lib_t2 = """}); +""" + +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, string_types): + lib = [lib] + elif lib is None: + lib = [] + if isinstance(css, string_types): + 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 + w4h4 = data[ihdr+4:ihdr+12] + return struct.unpack('>ii', w4h4) + +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 + +class Image(DisplayObject): + + _read_flags = 'rb' + _FMT_JPEG = u'jpeg' + _FMT_PNG = u'png' + _ACCEPTABLE_EMBEDDINGS = [_FMT_JPEG, _FMT_PNG] + + def __init__(self, data=None, url=None, filename=None, format=None, + embed=None, width=None, height=None, retina=False, + unconfined=False, metadata=None): + """Create a PNG/JPEG 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). 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 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 : 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. - - 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('http://www.google.fr/images/srpr/logo3w.png') - Image('/path/to/image.jpg') - Image(b'RAW_PNG_DATA...') - - # Specifying Image(url=...) does not embed the image data, - # it only generates `` tag with a link to the source. - # This will not work in the qtconsole or offline. - Image(url='http://www.google.fr/images/srpr/logo3w.png') - - """ - 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, string_types) 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 + 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. + + 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('http://www.google.fr/images/srpr/logo3w.png') + Image('/path/to/image.jpg') + Image(b'RAW_PNG_DATA...') + + # Specifying Image(url=...) does not embed the image data, + # it only generates `` tag with a link to the source. + # This will not work in the qtconsole or offline. + Image(url='http://www.google.fr/images/srpr/logo3w.png') + + """ + 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, string_types) 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 - 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 = 'png' - - if format.lower() == 'jpg': - # jpg->jpeg - format = self._FMT_JPEG - - self.format = unicode_type(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)) - self.width = width - self.height = height - self.retina = retina - self.unconfined = unconfined - self.metadata = metadata - super(Image, self).__init__(data=data, url=url, filename=filename) - - 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 == 'png': - w, h = _pngxy(self.data) - elif self.format == 'jpeg': - w, h = _jpegxy(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 = '' - if self.width: - width = ' width="%d"' % self.width - if self.height: - height = ' height="%d"' % self.height - if self.unconfined: - klass = ' class="unconfined"' - return u''.format( - url=self.url, - width=width, - height=height, - klass=klass, - ) - - def _data_and_metadata(self): - """shortcut for returning metadata with shape information, if defined""" - md = {} - if self.width: - md['width'] = self.width - if self.height: - md['height'] = self.height - if self.unconfined: - md['unconfined'] = self.unconfined - if self.metadata: - md.update(self.metadata) - if md: - return self.data, md - else: - return self.data - - def _repr_png_(self): - if self.embed and self.format == u'png': - return self._data_and_metadata() - - def _repr_jpeg_(self): - if self.embed and (self.format == u'jpeg' or self.format == u'jpg'): - return self._data_and_metadata() - - def _find_ext(self, s): - return unicode_type(s.split('.')[-1].lower()) - -class Video(DisplayObject): - + format = self._FMT_PNG + 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 = 'png' + + if format.lower() == 'jpg': + # jpg->jpeg + format = self._FMT_JPEG + + self.format = unicode_type(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)) + self.width = width + self.height = height + self.retina = retina + self.unconfined = unconfined + self.metadata = metadata + super(Image, self).__init__(data=data, url=url, filename=filename) + + 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 == 'png': + w, h = _pngxy(self.data) + elif self.format == 'jpeg': + w, h = _jpegxy(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 = '' + if self.width: + width = ' width="%d"' % self.width + if self.height: + height = ' height="%d"' % self.height + if self.unconfined: + klass = ' class="unconfined"' + return u''.format( + url=self.url, + width=width, + height=height, + klass=klass, + ) + + def _data_and_metadata(self): + """shortcut for returning metadata with shape information, if defined""" + md = {} + if self.width: + md['width'] = self.width + if self.height: + md['height'] = self.height + if self.unconfined: + md['unconfined'] = self.unconfined + if self.metadata: + md.update(self.metadata) + if md: + return self.data, md + else: + return self.data + + def _repr_png_(self): + if self.embed and self.format == u'png': + return self._data_and_metadata() + + def _repr_jpeg_(self): + if self.embed and (self.format == u'jpeg' or self.format == u'jpg'): + return self._data_and_metadata() + + def _find_ext(self, s): + return unicode_type(s.split('.')[-1].lower()) + +class Video(DisplayObject): + def __init__(self, data=None, url=None, filename=None, embed=False, mimetype=None): - """Create a video object given raw data or an URL. - - When this object is returned by an input cell or passed to the - display function, it will result in the video being displayed - in the frontend. - - Parameters - ---------- - data : unicode, str or bytes + """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 + url : unicode A URL for the video. If you specify `url=`, the image data will not be embedded. - filename : unicode + filename : unicode Path to a local file containing the video. Will be interpreted as a local URL unless `embed=True`. - embed : bool + embed : bool Should the video be embedded using a data URI (True) or be loaded using a