##// END OF EJS Templates
Merge remote-tracking branch 'origin/master' into inputtransformer2
Matthias Bussonnier -
r24499:7ad21738 merge
parent child Browse files
Show More

The requested changes are too big and content was truncated. Show full diff

1 NO CONTENT: new file 100644
NO CONTENT: new file 100644
The requested commit or file is too big and content was truncated. Show full diff
@@ -1,26 +1,29 b''
1 MANIFEST
1 MANIFEST
2 build
2 build
3 dist
3 dist
4 _build
4 _build
5 docs/man/*.gz
5 docs/man/*.gz
6 docs/source/api/generated
6 docs/source/api/generated
7 docs/source/config/options
7 docs/source/config/options
8 docs/source/config/shortcuts/*.csv
8 docs/source/config/shortcuts/*.csv
9 docs/source/interactive/magics-generated.txt
9 docs/source/interactive/magics-generated.txt
10 docs/source/config/shortcuts/*.csv
10 docs/source/config/shortcuts/*.csv
11 docs/gh-pages
11 docs/gh-pages
12 jupyter_notebook/notebook/static/mathjax
12 jupyter_notebook/notebook/static/mathjax
13 jupyter_notebook/static/style/*.map
13 jupyter_notebook/static/style/*.map
14 *.py[co]
14 *.py[co]
15 __pycache__
15 __pycache__
16 *.egg-info
16 *.egg-info
17 *~
17 *~
18 *.bak
18 *.bak
19 .ipynb_checkpoints
19 .ipynb_checkpoints
20 .tox
20 .tox
21 .DS_Store
21 .DS_Store
22 \#*#
22 \#*#
23 .#*
23 .#*
24 .cache
24 .cache
25 .coverage
25 .coverage
26 *.swp
26 *.swp
27 .vscode
28 .pytest_cache
29 .python-version
@@ -1,55 +1,56 b''
1 # http://travis-ci.org/#!/ipython/ipython
1 # http://travis-ci.org/#!/ipython/ipython
2 language: python
2 language: python
3 python:
3 python:
4 - "nightly"
4 - "nightly"
5 - "3.7-dev"
5 - "3.7-dev"
6 - 3.6
6 - 3.6
7 - 3.5
7 - 3.5
8 - 3.4
8 - 3.4
9 sudo: false
9 sudo: false
10 env:
10 env:
11 global:
11 global:
12 - PATH=$TRAVIS_BUILD_DIR/pandoc:$PATH
12 - PATH=$TRAVIS_BUILD_DIR/pandoc:$PATH
13 group: edge
13 group: edge
14 before_install:
14 before_install:
15 - 'if [[ $GROUP != js* ]]; then COVERAGE=""; fi'
15 - 'if [[ $GROUP != js* ]]; then COVERAGE=""; fi'
16 install:
16 install:
17 - pip install setuptools pip --upgrade
17 - pip install pip --upgrade
18 - pip install setuptools --upgrade
18 - pip install -e file://$PWD#egg=ipython[test] --upgrade
19 - pip install -e file://$PWD#egg=ipython[test] --upgrade
19 - pip install codecov check-manifest --upgrade
20 - pip install codecov check-manifest --upgrade
20 - sudo apt-get install graphviz
21 - sudo apt-get install graphviz
21 script:
22 script:
22 - check-manifest
23 - check-manifest
23 - cd /tmp && iptest --coverage xml && cd -
24 - cd /tmp && iptest --coverage xml && cd -
24 # On the latest Python only, make sure that the docs build.
25 # On the latest Python only, make sure that the docs build.
25 - |
26 - |
26 if [[ "$TRAVIS_PYTHON_VERSION" == "3.6" ]]; then
27 if [[ "$TRAVIS_PYTHON_VERSION" == "3.6" ]]; then
27 pip install -r docs/requirements.txt
28 pip install -r docs/requirements.txt
28 make -C docs/ html SPHINXOPTS="-W"
29 make -C docs/ html SPHINXOPTS="-W"
29 fi
30 fi
30 after_success:
31 after_success:
31 - cp /tmp/ipy_coverage.xml ./
32 - cp /tmp/ipy_coverage.xml ./
32 - cp /tmp/.coverage ./
33 - cp /tmp/.coverage ./
33 - codecov
34 - codecov
34
35
35 matrix:
36 matrix:
36 allow_failures:
37 allow_failures:
37 - python: nightly
38 - python: nightly
38
39
39 before_deploy:
40 before_deploy:
40 - rm -rf dist/
41 - rm -rf dist/
41 - python setup.py sdist
42 - python setup.py sdist
42 - python setup.py bdist_wheel
43 - python setup.py bdist_wheel
43
44
44 deploy:
45 deploy:
45 provider: releases
46 provider: releases
46 api_key:
47 api_key:
47 secure: Y/Ae9tYs5aoBU8bDjN2YrwGG6tCbezj/h3Lcmtx8HQavSbBgXnhnZVRb2snOKD7auqnqjfT/7QMm4ZyKvaOEgyggGktKqEKYHC8KOZ7yp8I5/UMDtk6j9TnXpSqqBxPiud4MDV76SfRYEQiaDoG4tGGvSfPJ9KcNjKrNvSyyxns=
48 secure: Y/Ae9tYs5aoBU8bDjN2YrwGG6tCbezj/h3Lcmtx8HQavSbBgXnhnZVRb2snOKD7auqnqjfT/7QMm4ZyKvaOEgyggGktKqEKYHC8KOZ7yp8I5/UMDtk6j9TnXpSqqBxPiud4MDV76SfRYEQiaDoG4tGGvSfPJ9KcNjKrNvSyyxns=
48 file: dist/*
49 file: dist/*
49 file_glob: true
50 file_glob: true
50 skip_cleanup: true
51 skip_cleanup: true
51 on:
52 on:
52 repo: ipython/ipython
53 repo: ipython/ipython
53 all_branches: true # Backports are released from e.g. 5.x branch
54 all_branches: true # Backports are released from e.g. 5.x branch
54 tags: true
55 tags: true
55 python: 3.6 # Any version should work, but we only need one
56 python: 3.6 # Any version should work, but we only need one
@@ -1,151 +1,151 b''
1 # encoding: utf-8
1 # encoding: utf-8
2 """
2 """
3 IPython: tools for interactive and parallel computing in Python.
3 IPython: tools for interactive and parallel computing in Python.
4
4
5 http://ipython.org
5 https://ipython.org
6 """
6 """
7 #-----------------------------------------------------------------------------
7 #-----------------------------------------------------------------------------
8 # Copyright (c) 2008-2011, IPython Development Team.
8 # Copyright (c) 2008-2011, IPython Development Team.
9 # Copyright (c) 2001-2007, Fernando Perez <fernando.perez@colorado.edu>
9 # Copyright (c) 2001-2007, Fernando Perez <fernando.perez@colorado.edu>
10 # Copyright (c) 2001, Janko Hauser <jhauser@zscout.de>
10 # Copyright (c) 2001, Janko Hauser <jhauser@zscout.de>
11 # Copyright (c) 2001, Nathaniel Gray <n8gray@caltech.edu>
11 # Copyright (c) 2001, Nathaniel Gray <n8gray@caltech.edu>
12 #
12 #
13 # Distributed under the terms of the Modified BSD License.
13 # Distributed under the terms of the Modified BSD License.
14 #
14 #
15 # The full license is in the file COPYING.txt, distributed with this software.
15 # The full license is in the file COPYING.txt, distributed with this software.
16 #-----------------------------------------------------------------------------
16 #-----------------------------------------------------------------------------
17
17
18 #-----------------------------------------------------------------------------
18 #-----------------------------------------------------------------------------
19 # Imports
19 # Imports
20 #-----------------------------------------------------------------------------
20 #-----------------------------------------------------------------------------
21
21
22 import os
22 import os
23 import sys
23 import sys
24
24
25 #-----------------------------------------------------------------------------
25 #-----------------------------------------------------------------------------
26 # Setup everything
26 # Setup everything
27 #-----------------------------------------------------------------------------
27 #-----------------------------------------------------------------------------
28
28
29 # Don't forget to also update setup.py when this changes!
29 # Don't forget to also update setup.py when this changes!
30 if sys.version_info < (3,4):
30 if sys.version_info < (3,4):
31 raise ImportError(
31 raise ImportError(
32 """
32 """
33 IPython 7.0+ supports Python 3.4 and above.
33 IPython 7.0+ supports Python 3.4 and above.
34 When using Python 2.7, please install IPython 5.x LTS Long Term Support version.
34 When using Python 2.7, please install IPython 5.x LTS Long Term Support version.
35 Python 3.3 was supported up to IPython 6.x.
35 Python 3.3 was supported up to IPython 6.x.
36
36
37 See IPython `README.rst` file for more information:
37 See IPython `README.rst` file for more information:
38
38
39 https://github.com/ipython/ipython/blob/master/README.rst
39 https://github.com/ipython/ipython/blob/master/README.rst
40
40
41 """)
41 """)
42
42
43 # Make it easy to import extensions - they are always directly on pythonpath.
43 # Make it easy to import extensions - they are always directly on pythonpath.
44 # Therefore, non-IPython modules can be added to extensions directory.
44 # Therefore, non-IPython modules can be added to extensions directory.
45 # This should probably be in ipapp.py.
45 # This should probably be in ipapp.py.
46 sys.path.append(os.path.join(os.path.dirname(__file__), "extensions"))
46 sys.path.append(os.path.join(os.path.dirname(__file__), "extensions"))
47
47
48 #-----------------------------------------------------------------------------
48 #-----------------------------------------------------------------------------
49 # Setup the top level names
49 # Setup the top level names
50 #-----------------------------------------------------------------------------
50 #-----------------------------------------------------------------------------
51
51
52 from .core.getipython import get_ipython
52 from .core.getipython import get_ipython
53 from .core import release
53 from .core import release
54 from .core.application import Application
54 from .core.application import Application
55 from .terminal.embed import embed
55 from .terminal.embed import embed
56
56
57 from .core.interactiveshell import InteractiveShell
57 from .core.interactiveshell import InteractiveShell
58 from .testing import test
58 from .testing import test
59 from .utils.sysinfo import sys_info
59 from .utils.sysinfo import sys_info
60 from .utils.frame import extract_module_locals
60 from .utils.frame import extract_module_locals
61
61
62 # Release data
62 # Release data
63 __author__ = '%s <%s>' % (release.author, release.author_email)
63 __author__ = '%s <%s>' % (release.author, release.author_email)
64 __license__ = release.license
64 __license__ = release.license
65 __version__ = release.version
65 __version__ = release.version
66 version_info = release.version_info
66 version_info = release.version_info
67
67
68 def embed_kernel(module=None, local_ns=None, **kwargs):
68 def embed_kernel(module=None, local_ns=None, **kwargs):
69 """Embed and start an IPython kernel in a given scope.
69 """Embed and start an IPython kernel in a given scope.
70
70
71 If you don't want the kernel to initialize the namespace
71 If you don't want the kernel to initialize the namespace
72 from the scope of the surrounding function,
72 from the scope of the surrounding function,
73 and/or you want to load full IPython configuration,
73 and/or you want to load full IPython configuration,
74 you probably want `IPython.start_kernel()` instead.
74 you probably want `IPython.start_kernel()` instead.
75
75
76 Parameters
76 Parameters
77 ----------
77 ----------
78 module : ModuleType, optional
78 module : ModuleType, optional
79 The module to load into IPython globals (default: caller)
79 The module to load into IPython globals (default: caller)
80 local_ns : dict, optional
80 local_ns : dict, optional
81 The namespace to load into IPython user namespace (default: caller)
81 The namespace to load into IPython user namespace (default: caller)
82
82
83 kwargs : various, optional
83 kwargs : various, optional
84 Further keyword args are relayed to the IPKernelApp constructor,
84 Further keyword args are relayed to the IPKernelApp constructor,
85 allowing configuration of the Kernel. Will only have an effect
85 allowing configuration of the Kernel. Will only have an effect
86 on the first embed_kernel call for a given process.
86 on the first embed_kernel call for a given process.
87 """
87 """
88
88
89 (caller_module, caller_locals) = extract_module_locals(1)
89 (caller_module, caller_locals) = extract_module_locals(1)
90 if module is None:
90 if module is None:
91 module = caller_module
91 module = caller_module
92 if local_ns is None:
92 if local_ns is None:
93 local_ns = caller_locals
93 local_ns = caller_locals
94
94
95 # Only import .zmq when we really need it
95 # Only import .zmq when we really need it
96 from ipykernel.embed import embed_kernel as real_embed_kernel
96 from ipykernel.embed import embed_kernel as real_embed_kernel
97 real_embed_kernel(module=module, local_ns=local_ns, **kwargs)
97 real_embed_kernel(module=module, local_ns=local_ns, **kwargs)
98
98
99 def start_ipython(argv=None, **kwargs):
99 def start_ipython(argv=None, **kwargs):
100 """Launch a normal IPython instance (as opposed to embedded)
100 """Launch a normal IPython instance (as opposed to embedded)
101
101
102 `IPython.embed()` puts a shell in a particular calling scope,
102 `IPython.embed()` puts a shell in a particular calling scope,
103 such as a function or method for debugging purposes,
103 such as a function or method for debugging purposes,
104 which is often not desirable.
104 which is often not desirable.
105
105
106 `start_ipython()` does full, regular IPython initialization,
106 `start_ipython()` does full, regular IPython initialization,
107 including loading startup files, configuration, etc.
107 including loading startup files, configuration, etc.
108 much of which is skipped by `embed()`.
108 much of which is skipped by `embed()`.
109
109
110 This is a public API method, and will survive implementation changes.
110 This is a public API method, and will survive implementation changes.
111
111
112 Parameters
112 Parameters
113 ----------
113 ----------
114
114
115 argv : list or None, optional
115 argv : list or None, optional
116 If unspecified or None, IPython will parse command-line options from sys.argv.
116 If unspecified or None, IPython will parse command-line options from sys.argv.
117 To prevent any command-line parsing, pass an empty list: `argv=[]`.
117 To prevent any command-line parsing, pass an empty list: `argv=[]`.
118 user_ns : dict, optional
118 user_ns : dict, optional
119 specify this dictionary to initialize the IPython user namespace with particular values.
119 specify this dictionary to initialize the IPython user namespace with particular values.
120 kwargs : various, optional
120 kwargs : various, optional
121 Any other kwargs will be passed to the Application constructor,
121 Any other kwargs will be passed to the Application constructor,
122 such as `config`.
122 such as `config`.
123 """
123 """
124 from IPython.terminal.ipapp import launch_new_instance
124 from IPython.terminal.ipapp import launch_new_instance
125 return launch_new_instance(argv=argv, **kwargs)
125 return launch_new_instance(argv=argv, **kwargs)
126
126
127 def start_kernel(argv=None, **kwargs):
127 def start_kernel(argv=None, **kwargs):
128 """Launch a normal IPython kernel instance (as opposed to embedded)
128 """Launch a normal IPython kernel instance (as opposed to embedded)
129
129
130 `IPython.embed_kernel()` puts a shell in a particular calling scope,
130 `IPython.embed_kernel()` puts a shell in a particular calling scope,
131 such as a function or method for debugging purposes,
131 such as a function or method for debugging purposes,
132 which is often not desirable.
132 which is often not desirable.
133
133
134 `start_kernel()` does full, regular IPython initialization,
134 `start_kernel()` does full, regular IPython initialization,
135 including loading startup files, configuration, etc.
135 including loading startup files, configuration, etc.
136 much of which is skipped by `embed()`.
136 much of which is skipped by `embed()`.
137
137
138 Parameters
138 Parameters
139 ----------
139 ----------
140
140
141 argv : list or None, optional
141 argv : list or None, optional
142 If unspecified or None, IPython will parse command-line options from sys.argv.
142 If unspecified or None, IPython will parse command-line options from sys.argv.
143 To prevent any command-line parsing, pass an empty list: `argv=[]`.
143 To prevent any command-line parsing, pass an empty list: `argv=[]`.
144 user_ns : dict, optional
144 user_ns : dict, optional
145 specify this dictionary to initialize the IPython user namespace with particular values.
145 specify this dictionary to initialize the IPython user namespace with particular values.
146 kwargs : various, optional
146 kwargs : various, optional
147 Any other kwargs will be passed to the Application constructor,
147 Any other kwargs will be passed to the Application constructor,
148 such as `config`.
148 such as `config`.
149 """
149 """
150 from IPython.kernel.zmq.kernelapp import launch_new_instance
150 from IPython.kernel.zmq.kernelapp import launch_new_instance
151 return launch_new_instance(argv=argv, **kwargs)
151 return launch_new_instance(argv=argv, **kwargs)
@@ -1,161 +1,161 b''
1 """Compiler tools with improved interactive support.
1 """Compiler tools with improved interactive support.
2
2
3 Provides compilation machinery similar to codeop, but with caching support so
3 Provides compilation machinery similar to codeop, but with caching support so
4 we can provide interactive tracebacks.
4 we can provide interactive tracebacks.
5
5
6 Authors
6 Authors
7 -------
7 -------
8 * Robert Kern
8 * Robert Kern
9 * Fernando Perez
9 * Fernando Perez
10 * Thomas Kluyver
10 * Thomas Kluyver
11 """
11 """
12
12
13 # Note: though it might be more natural to name this module 'compiler', that
13 # Note: though it might be more natural to name this module 'compiler', that
14 # name is in the stdlib and name collisions with the stdlib tend to produce
14 # name is in the stdlib and name collisions with the stdlib tend to produce
15 # weird problems (often with third-party tools).
15 # weird problems (often with third-party tools).
16
16
17 #-----------------------------------------------------------------------------
17 #-----------------------------------------------------------------------------
18 # Copyright (C) 2010-2011 The IPython Development Team.
18 # Copyright (C) 2010-2011 The IPython Development Team.
19 #
19 #
20 # Distributed under the terms of the BSD License.
20 # Distributed under the terms of the BSD License.
21 #
21 #
22 # The full license is in the file COPYING.txt, distributed with this software.
22 # The full license is in the file COPYING.txt, distributed with this software.
23 #-----------------------------------------------------------------------------
23 #-----------------------------------------------------------------------------
24
24
25 #-----------------------------------------------------------------------------
25 #-----------------------------------------------------------------------------
26 # Imports
26 # Imports
27 #-----------------------------------------------------------------------------
27 #-----------------------------------------------------------------------------
28
28
29 # Stdlib imports
29 # Stdlib imports
30 import __future__
30 import __future__
31 from ast import PyCF_ONLY_AST
31 from ast import PyCF_ONLY_AST
32 import codeop
32 import codeop
33 import functools
33 import functools
34 import hashlib
34 import hashlib
35 import linecache
35 import linecache
36 import operator
36 import operator
37 import time
37 import time
38
38
39 #-----------------------------------------------------------------------------
39 #-----------------------------------------------------------------------------
40 # Constants
40 # Constants
41 #-----------------------------------------------------------------------------
41 #-----------------------------------------------------------------------------
42
42
43 # Roughtly equal to PyCF_MASK | PyCF_MASK_OBSOLETE as defined in pythonrun.h,
43 # Roughly equal to PyCF_MASK | PyCF_MASK_OBSOLETE as defined in pythonrun.h,
44 # this is used as a bitmask to extract future-related code flags.
44 # this is used as a bitmask to extract future-related code flags.
45 PyCF_MASK = functools.reduce(operator.or_,
45 PyCF_MASK = functools.reduce(operator.or_,
46 (getattr(__future__, fname).compiler_flag
46 (getattr(__future__, fname).compiler_flag
47 for fname in __future__.all_feature_names))
47 for fname in __future__.all_feature_names))
48
48
49 #-----------------------------------------------------------------------------
49 #-----------------------------------------------------------------------------
50 # Local utilities
50 # Local utilities
51 #-----------------------------------------------------------------------------
51 #-----------------------------------------------------------------------------
52
52
53 def code_name(code, number=0):
53 def code_name(code, number=0):
54 """ Compute a (probably) unique name for code for caching.
54 """ Compute a (probably) unique name for code for caching.
55
55
56 This now expects code to be unicode.
56 This now expects code to be unicode.
57 """
57 """
58 hash_digest = hashlib.sha1(code.encode("utf-8")).hexdigest()
58 hash_digest = hashlib.sha1(code.encode("utf-8")).hexdigest()
59 # Include the number and 12 characters of the hash in the name. It's
59 # Include the number and 12 characters of the hash in the name. It's
60 # pretty much impossible that in a single session we'll have collisions
60 # pretty much impossible that in a single session we'll have collisions
61 # even with truncated hashes, and the full one makes tracebacks too long
61 # even with truncated hashes, and the full one makes tracebacks too long
62 return '<ipython-input-{0}-{1}>'.format(number, hash_digest[:12])
62 return '<ipython-input-{0}-{1}>'.format(number, hash_digest[:12])
63
63
64 #-----------------------------------------------------------------------------
64 #-----------------------------------------------------------------------------
65 # Classes and functions
65 # Classes and functions
66 #-----------------------------------------------------------------------------
66 #-----------------------------------------------------------------------------
67
67
68 class CachingCompiler(codeop.Compile):
68 class CachingCompiler(codeop.Compile):
69 """A compiler that caches code compiled from interactive statements.
69 """A compiler that caches code compiled from interactive statements.
70 """
70 """
71
71
72 def __init__(self):
72 def __init__(self):
73 codeop.Compile.__init__(self)
73 codeop.Compile.__init__(self)
74
74
75 # This is ugly, but it must be done this way to allow multiple
75 # This is ugly, but it must be done this way to allow multiple
76 # simultaneous ipython instances to coexist. Since Python itself
76 # simultaneous ipython instances to coexist. Since Python itself
77 # directly accesses the data structures in the linecache module, and
77 # directly accesses the data structures in the linecache module, and
78 # the cache therein is global, we must work with that data structure.
78 # the cache therein is global, we must work with that data structure.
79 # We must hold a reference to the original checkcache routine and call
79 # We must hold a reference to the original checkcache routine and call
80 # that in our own check_cache() below, but the special IPython cache
80 # that in our own check_cache() below, but the special IPython cache
81 # must also be shared by all IPython instances. If we were to hold
81 # must also be shared by all IPython instances. If we were to hold
82 # separate caches (one in each CachingCompiler instance), any call made
82 # separate caches (one in each CachingCompiler instance), any call made
83 # by Python itself to linecache.checkcache() would obliterate the
83 # by Python itself to linecache.checkcache() would obliterate the
84 # cached data from the other IPython instances.
84 # cached data from the other IPython instances.
85 if not hasattr(linecache, '_ipython_cache'):
85 if not hasattr(linecache, '_ipython_cache'):
86 linecache._ipython_cache = {}
86 linecache._ipython_cache = {}
87 if not hasattr(linecache, '_checkcache_ori'):
87 if not hasattr(linecache, '_checkcache_ori'):
88 linecache._checkcache_ori = linecache.checkcache
88 linecache._checkcache_ori = linecache.checkcache
89 # Now, we must monkeypatch the linecache directly so that parts of the
89 # Now, we must monkeypatch the linecache directly so that parts of the
90 # stdlib that call it outside our control go through our codepath
90 # stdlib that call it outside our control go through our codepath
91 # (otherwise we'd lose our tracebacks).
91 # (otherwise we'd lose our tracebacks).
92 linecache.checkcache = check_linecache_ipython
92 linecache.checkcache = check_linecache_ipython
93
93
94
94
95 def _fix_module_ds(self, module):
95 def _fix_module_ds(self, module):
96 """
96 """
97 Starting in python 3.7 the AST for mule have changed, and if
97 Starting in python 3.7 the AST for mule have changed, and if
98 the first expressions encountered is a string it is attached to the
98 the first expressions encountered is a string it is attached to the
99 `docstring` attribute of the `Module` ast node.
99 `docstring` attribute of the `Module` ast node.
100
100
101 This breaks IPython, as if this string is the only expression, IPython
101 This breaks IPython, as if this string is the only expression, IPython
102 will not return it as the result of the current cell.
102 will not return it as the result of the current cell.
103 """
103 """
104 from ast import Str, Expr, Module, fix_missing_locations
104 from ast import Str, Expr, Module, fix_missing_locations
105 docstring = getattr(module, 'docstring', None)
105 docstring = getattr(module, 'docstring', None)
106 if not docstring:
106 if not docstring:
107 return module
107 return module
108 new_body=[Expr(Str(docstring, lineno=1, col_offset=0), lineno=1, col_offset=0)]
108 new_body=[Expr(Str(docstring, lineno=1, col_offset=0), lineno=1, col_offset=0)]
109 new_body.extend(module.body)
109 new_body.extend(module.body)
110 return fix_missing_locations(Module(new_body))
110 return fix_missing_locations(Module(new_body))
111
111
112 def ast_parse(self, source, filename='<unknown>', symbol='exec'):
112 def ast_parse(self, source, filename='<unknown>', symbol='exec'):
113 """Parse code to an AST with the current compiler flags active.
113 """Parse code to an AST with the current compiler flags active.
114
114
115 Arguments are exactly the same as ast.parse (in the standard library),
115 Arguments are exactly the same as ast.parse (in the standard library),
116 and are passed to the built-in compile function."""
116 and are passed to the built-in compile function."""
117 return self._fix_module_ds(compile(source, filename, symbol, self.flags | PyCF_ONLY_AST, 1))
117 return self._fix_module_ds(compile(source, filename, symbol, self.flags | PyCF_ONLY_AST, 1))
118
118
119 def reset_compiler_flags(self):
119 def reset_compiler_flags(self):
120 """Reset compiler flags to default state."""
120 """Reset compiler flags to default state."""
121 # This value is copied from codeop.Compile.__init__, so if that ever
121 # This value is copied from codeop.Compile.__init__, so if that ever
122 # changes, it will need to be updated.
122 # changes, it will need to be updated.
123 self.flags = codeop.PyCF_DONT_IMPLY_DEDENT
123 self.flags = codeop.PyCF_DONT_IMPLY_DEDENT
124
124
125 @property
125 @property
126 def compiler_flags(self):
126 def compiler_flags(self):
127 """Flags currently active in the compilation process.
127 """Flags currently active in the compilation process.
128 """
128 """
129 return self.flags
129 return self.flags
130
130
131 def cache(self, code, number=0):
131 def cache(self, code, number=0):
132 """Make a name for a block of code, and cache the code.
132 """Make a name for a block of code, and cache the code.
133
133
134 Parameters
134 Parameters
135 ----------
135 ----------
136 code : str
136 code : str
137 The Python source code to cache.
137 The Python source code to cache.
138 number : int
138 number : int
139 A number which forms part of the code's name. Used for the execution
139 A number which forms part of the code's name. Used for the execution
140 counter.
140 counter.
141
141
142 Returns
142 Returns
143 -------
143 -------
144 The name of the cached code (as a string). Pass this as the filename
144 The name of the cached code (as a string). Pass this as the filename
145 argument to compilation, so that tracebacks are correctly hooked up.
145 argument to compilation, so that tracebacks are correctly hooked up.
146 """
146 """
147 name = code_name(code, number)
147 name = code_name(code, number)
148 entry = (len(code), time.time(),
148 entry = (len(code), time.time(),
149 [line+'\n' for line in code.splitlines()], name)
149 [line+'\n' for line in code.splitlines()], name)
150 linecache.cache[name] = entry
150 linecache.cache[name] = entry
151 linecache._ipython_cache[name] = entry
151 linecache._ipython_cache[name] = entry
152 return name
152 return name
153
153
154 def check_linecache_ipython(*args):
154 def check_linecache_ipython(*args):
155 """Call linecache.checkcache() safely protecting our cached values.
155 """Call linecache.checkcache() safely protecting our cached values.
156 """
156 """
157 # First call the original checkcache as intended
157 # First call the original checkcache as intended
158 linecache._checkcache_ori(*args)
158 linecache._checkcache_ori(*args)
159 # Then, update back the cache with our data, so that tracebacks related
159 # Then, update back the cache with our data, so that tracebacks related
160 # to our compiled codes can be produced.
160 # to our compiled codes can be produced.
161 linecache.cache.update(linecache._ipython_cache)
161 linecache.cache.update(linecache._ipython_cache)
@@ -1,2060 +1,2060 b''
1 """Completion for IPython.
1 """Completion for IPython.
2
2
3 This module started as fork of the rlcompleter module in the Python standard
3 This module started as fork of the rlcompleter module in the Python standard
4 library. The original enhancements made to rlcompleter have been sent
4 library. The original enhancements made to rlcompleter have been sent
5 upstream and were accepted as of Python 2.3,
5 upstream and were accepted as of Python 2.3,
6
6
7 This module now support a wide variety of completion mechanism both available
7 This module now support a wide variety of completion mechanism both available
8 for normal classic Python code, as well as completer for IPython specific
8 for normal classic Python code, as well as completer for IPython specific
9 Syntax like magics.
9 Syntax like magics.
10
10
11 Latex and Unicode completion
11 Latex and Unicode completion
12 ============================
12 ============================
13
13
14 IPython and compatible frontends not only can complete your code, but can help
14 IPython and compatible frontends not only can complete your code, but can help
15 you to input a wide range of characters. In particular we allow you to insert
15 you to input a wide range of characters. In particular we allow you to insert
16 a unicode character using the tab completion mechanism.
16 a unicode character using the tab completion mechanism.
17
17
18 Forward latex/unicode completion
18 Forward latex/unicode completion
19 --------------------------------
19 --------------------------------
20
20
21 Forward completion allows you to easily type a unicode character using its latex
21 Forward completion allows you to easily type a unicode character using its latex
22 name, or unicode long description. To do so type a backslash follow by the
22 name, or unicode long description. To do so type a backslash follow by the
23 relevant name and press tab:
23 relevant name and press tab:
24
24
25
25
26 Using latex completion:
26 Using latex completion:
27
27
28 .. code::
28 .. code::
29
29
30 \\alpha<tab>
30 \\alpha<tab>
31 α
31 α
32
32
33 or using unicode completion:
33 or using unicode completion:
34
34
35
35
36 .. code::
36 .. code::
37
37
38 \\greek small letter alpha<tab>
38 \\greek small letter alpha<tab>
39 α
39 α
40
40
41
41
42 Only valid Python identifiers will complete. Combining characters (like arrow or
42 Only valid Python identifiers will complete. Combining characters (like arrow or
43 dots) are also available, unlike latex they need to be put after the their
43 dots) are also available, unlike latex they need to be put after the their
44 counterpart that is to say, `F\\\\vec<tab>` is correct, not `\\\\vec<tab>F`.
44 counterpart that is to say, `F\\\\vec<tab>` is correct, not `\\\\vec<tab>F`.
45
45
46 Some browsers are known to display combining characters incorrectly.
46 Some browsers are known to display combining characters incorrectly.
47
47
48 Backward latex completion
48 Backward latex completion
49 -------------------------
49 -------------------------
50
50
51 It is sometime challenging to know how to type a character, if you are using
51 It is sometime challenging to know how to type a character, if you are using
52 IPython, or any compatible frontend you can prepend backslash to the character
52 IPython, or any compatible frontend you can prepend backslash to the character
53 and press `<tab>` to expand it to its latex form.
53 and press `<tab>` to expand it to its latex form.
54
54
55 .. code::
55 .. code::
56
56
57 \\α<tab>
57 \\α<tab>
58 \\alpha
58 \\alpha
59
59
60
60
61 Both forward and backward completions can be deactivated by setting the
61 Both forward and backward completions can be deactivated by setting the
62 ``Completer.backslash_combining_completions`` option to ``False``.
62 ``Completer.backslash_combining_completions`` option to ``False``.
63
63
64
64
65 Experimental
65 Experimental
66 ============
66 ============
67
67
68 Starting with IPython 6.0, this module can make use of the Jedi library to
68 Starting with IPython 6.0, this module can make use of the Jedi library to
69 generate completions both using static analysis of the code, and dynamically
69 generate completions both using static analysis of the code, and dynamically
70 inspecting multiple namespaces. The APIs attached to this new mechanism is
70 inspecting multiple namespaces. The APIs attached to this new mechanism is
71 unstable and will raise unless use in an :any:`provisionalcompleter` context
71 unstable and will raise unless use in an :any:`provisionalcompleter` context
72 manager.
72 manager.
73
73
74 You will find that the following are experimental:
74 You will find that the following are experimental:
75
75
76 - :any:`provisionalcompleter`
76 - :any:`provisionalcompleter`
77 - :any:`IPCompleter.completions`
77 - :any:`IPCompleter.completions`
78 - :any:`Completion`
78 - :any:`Completion`
79 - :any:`rectify_completions`
79 - :any:`rectify_completions`
80
80
81 .. note::
81 .. note::
82
82
83 better name for :any:`rectify_completions` ?
83 better name for :any:`rectify_completions` ?
84
84
85 We welcome any feedback on these new API, and we also encourage you to try this
85 We welcome any feedback on these new API, and we also encourage you to try this
86 module in debug mode (start IPython with ``--Completer.debug=True``) in order
86 module in debug mode (start IPython with ``--Completer.debug=True``) in order
87 to have extra logging information is :any:`jedi` is crashing, or if current
87 to have extra logging information is :any:`jedi` is crashing, or if current
88 IPython completer pending deprecations are returning results not yet handled
88 IPython completer pending deprecations are returning results not yet handled
89 by :any:`jedi`
89 by :any:`jedi`
90
90
91 Using Jedi for tab completion allow snippets like the following to work without
91 Using Jedi for tab completion allow snippets like the following to work without
92 having to execute any code:
92 having to execute any code:
93
93
94 >>> myvar = ['hello', 42]
94 >>> myvar = ['hello', 42]
95 ... myvar[1].bi<tab>
95 ... myvar[1].bi<tab>
96
96
97 Tab completion will be able to infer that ``myvar[1]`` is a real number without
97 Tab completion will be able to infer that ``myvar[1]`` is a real number without
98 executing any code unlike the previously available ``IPCompleter.greedy``
98 executing any code unlike the previously available ``IPCompleter.greedy``
99 option.
99 option.
100
100
101 Be sure to update :any:`jedi` to the latest stable version or to try the
101 Be sure to update :any:`jedi` to the latest stable version or to try the
102 current development version to get better completions.
102 current development version to get better completions.
103 """
103 """
104
104
105
105
106 # Copyright (c) IPython Development Team.
106 # Copyright (c) IPython Development Team.
107 # Distributed under the terms of the Modified BSD License.
107 # Distributed under the terms of the Modified BSD License.
108 #
108 #
109 # Some of this code originated from rlcompleter in the Python standard library
109 # Some of this code originated from rlcompleter in the Python standard library
110 # Copyright (C) 2001 Python Software Foundation, www.python.org
110 # Copyright (C) 2001 Python Software Foundation, www.python.org
111
111
112
112
113 import __main__
113 import __main__
114 import builtins as builtin_mod
114 import builtins as builtin_mod
115 import glob
115 import glob
116 import time
116 import time
117 import inspect
117 import inspect
118 import itertools
118 import itertools
119 import keyword
119 import keyword
120 import os
120 import os
121 import re
121 import re
122 import sys
122 import sys
123 import unicodedata
123 import unicodedata
124 import string
124 import string
125 import warnings
125 import warnings
126
126
127 from contextlib import contextmanager
127 from contextlib import contextmanager
128 from importlib import import_module
128 from importlib import import_module
129 from typing import Iterator, List, Tuple, Iterable, Union
129 from typing import Iterator, List, Tuple, Iterable, Union
130 from types import SimpleNamespace
130 from types import SimpleNamespace
131
131
132 from traitlets.config.configurable import Configurable
132 from traitlets.config.configurable import Configurable
133 from IPython.core.error import TryNext
133 from IPython.core.error import TryNext
134 from IPython.core.inputtransformer2 import ESC_MAGIC
134 from IPython.core.inputtransformer2 import ESC_MAGIC
135 from IPython.core.latex_symbols import latex_symbols, reverse_latex_symbol
135 from IPython.core.latex_symbols import latex_symbols, reverse_latex_symbol
136 from IPython.core.oinspect import InspectColors
136 from IPython.core.oinspect import InspectColors
137 from IPython.utils import generics
137 from IPython.utils import generics
138 from IPython.utils.dir2 import dir2, get_real_method
138 from IPython.utils.dir2 import dir2, get_real_method
139 from IPython.utils.process import arg_split
139 from IPython.utils.process import arg_split
140 from traitlets import Bool, Enum, observe, Int
140 from traitlets import Bool, Enum, observe, Int
141
141
142 # skip module docstests
142 # skip module docstests
143 skip_doctest = True
143 skip_doctest = True
144
144
145 try:
145 try:
146 import jedi
146 import jedi
147 jedi.settings.case_insensitive_completion = False
147 jedi.settings.case_insensitive_completion = False
148 import jedi.api.helpers
148 import jedi.api.helpers
149 import jedi.api.classes
149 import jedi.api.classes
150 JEDI_INSTALLED = True
150 JEDI_INSTALLED = True
151 except ImportError:
151 except ImportError:
152 JEDI_INSTALLED = False
152 JEDI_INSTALLED = False
153 #-----------------------------------------------------------------------------
153 #-----------------------------------------------------------------------------
154 # Globals
154 # Globals
155 #-----------------------------------------------------------------------------
155 #-----------------------------------------------------------------------------
156
156
157 # Public API
157 # Public API
158 __all__ = ['Completer','IPCompleter']
158 __all__ = ['Completer','IPCompleter']
159
159
160 if sys.platform == 'win32':
160 if sys.platform == 'win32':
161 PROTECTABLES = ' '
161 PROTECTABLES = ' '
162 else:
162 else:
163 PROTECTABLES = ' ()[]{}?=\\|;:\'#*"^&'
163 PROTECTABLES = ' ()[]{}?=\\|;:\'#*"^&'
164
164
165 # Protect against returning an enormous number of completions which the frontend
165 # Protect against returning an enormous number of completions which the frontend
166 # may have trouble processing.
166 # may have trouble processing.
167 MATCHES_LIMIT = 500
167 MATCHES_LIMIT = 500
168
168
169 _deprecation_readline_sentinel = object()
169 _deprecation_readline_sentinel = object()
170
170
171
171
172 class ProvisionalCompleterWarning(FutureWarning):
172 class ProvisionalCompleterWarning(FutureWarning):
173 """
173 """
174 Exception raise by an experimental feature in this module.
174 Exception raise by an experimental feature in this module.
175
175
176 Wrap code in :any:`provisionalcompleter` context manager if you
176 Wrap code in :any:`provisionalcompleter` context manager if you
177 are certain you want to use an unstable feature.
177 are certain you want to use an unstable feature.
178 """
178 """
179 pass
179 pass
180
180
181 warnings.filterwarnings('error', category=ProvisionalCompleterWarning)
181 warnings.filterwarnings('error', category=ProvisionalCompleterWarning)
182
182
183 @contextmanager
183 @contextmanager
184 def provisionalcompleter(action='ignore'):
184 def provisionalcompleter(action='ignore'):
185 """
185 """
186
186
187
187
188 This contest manager has to be used in any place where unstable completer
188 This contest manager has to be used in any place where unstable completer
189 behavior and API may be called.
189 behavior and API may be called.
190
190
191 >>> with provisionalcompleter():
191 >>> with provisionalcompleter():
192 ... completer.do_experimetal_things() # works
192 ... completer.do_experimetal_things() # works
193
193
194 >>> completer.do_experimental_things() # raises.
194 >>> completer.do_experimental_things() # raises.
195
195
196 .. note:: Unstable
196 .. note:: Unstable
197
197
198 By using this context manager you agree that the API in use may change
198 By using this context manager you agree that the API in use may change
199 without warning, and that you won't complain if they do so.
199 without warning, and that you won't complain if they do so.
200
200
201 You also understand that if the API is not to you liking you should report
201 You also understand that if the API is not to you liking you should report
202 a bug to explain your use case upstream and improve the API and will loose
202 a bug to explain your use case upstream and improve the API and will loose
203 credibility if you complain after the API is make stable.
203 credibility if you complain after the API is make stable.
204
204
205 We'll be happy to get your feedback , feature request and improvement on
205 We'll be happy to get your feedback , feature request and improvement on
206 any of the unstable APIs !
206 any of the unstable APIs !
207 """
207 """
208 with warnings.catch_warnings():
208 with warnings.catch_warnings():
209 warnings.filterwarnings(action, category=ProvisionalCompleterWarning)
209 warnings.filterwarnings(action, category=ProvisionalCompleterWarning)
210 yield
210 yield
211
211
212
212
213 def has_open_quotes(s):
213 def has_open_quotes(s):
214 """Return whether a string has open quotes.
214 """Return whether a string has open quotes.
215
215
216 This simply counts whether the number of quote characters of either type in
216 This simply counts whether the number of quote characters of either type in
217 the string is odd.
217 the string is odd.
218
218
219 Returns
219 Returns
220 -------
220 -------
221 If there is an open quote, the quote character is returned. Else, return
221 If there is an open quote, the quote character is returned. Else, return
222 False.
222 False.
223 """
223 """
224 # We check " first, then ', so complex cases with nested quotes will get
224 # We check " first, then ', so complex cases with nested quotes will get
225 # the " to take precedence.
225 # the " to take precedence.
226 if s.count('"') % 2:
226 if s.count('"') % 2:
227 return '"'
227 return '"'
228 elif s.count("'") % 2:
228 elif s.count("'") % 2:
229 return "'"
229 return "'"
230 else:
230 else:
231 return False
231 return False
232
232
233
233
234 def protect_filename(s, protectables=PROTECTABLES):
234 def protect_filename(s, protectables=PROTECTABLES):
235 """Escape a string to protect certain characters."""
235 """Escape a string to protect certain characters."""
236 if set(s) & set(protectables):
236 if set(s) & set(protectables):
237 if sys.platform == "win32":
237 if sys.platform == "win32":
238 return '"' + s + '"'
238 return '"' + s + '"'
239 else:
239 else:
240 return "".join(("\\" + c if c in protectables else c) for c in s)
240 return "".join(("\\" + c if c in protectables else c) for c in s)
241 else:
241 else:
242 return s
242 return s
243
243
244
244
245 def expand_user(path:str) -> Tuple[str, bool, str]:
245 def expand_user(path:str) -> Tuple[str, bool, str]:
246 """Expand ``~``-style usernames in strings.
246 """Expand ``~``-style usernames in strings.
247
247
248 This is similar to :func:`os.path.expanduser`, but it computes and returns
248 This is similar to :func:`os.path.expanduser`, but it computes and returns
249 extra information that will be useful if the input was being used in
249 extra information that will be useful if the input was being used in
250 computing completions, and you wish to return the completions with the
250 computing completions, and you wish to return the completions with the
251 original '~' instead of its expanded value.
251 original '~' instead of its expanded value.
252
252
253 Parameters
253 Parameters
254 ----------
254 ----------
255 path : str
255 path : str
256 String to be expanded. If no ~ is present, the output is the same as the
256 String to be expanded. If no ~ is present, the output is the same as the
257 input.
257 input.
258
258
259 Returns
259 Returns
260 -------
260 -------
261 newpath : str
261 newpath : str
262 Result of ~ expansion in the input path.
262 Result of ~ expansion in the input path.
263 tilde_expand : bool
263 tilde_expand : bool
264 Whether any expansion was performed or not.
264 Whether any expansion was performed or not.
265 tilde_val : str
265 tilde_val : str
266 The value that ~ was replaced with.
266 The value that ~ was replaced with.
267 """
267 """
268 # Default values
268 # Default values
269 tilde_expand = False
269 tilde_expand = False
270 tilde_val = ''
270 tilde_val = ''
271 newpath = path
271 newpath = path
272
272
273 if path.startswith('~'):
273 if path.startswith('~'):
274 tilde_expand = True
274 tilde_expand = True
275 rest = len(path)-1
275 rest = len(path)-1
276 newpath = os.path.expanduser(path)
276 newpath = os.path.expanduser(path)
277 if rest:
277 if rest:
278 tilde_val = newpath[:-rest]
278 tilde_val = newpath[:-rest]
279 else:
279 else:
280 tilde_val = newpath
280 tilde_val = newpath
281
281
282 return newpath, tilde_expand, tilde_val
282 return newpath, tilde_expand, tilde_val
283
283
284
284
285 def compress_user(path:str, tilde_expand:bool, tilde_val:str) -> str:
285 def compress_user(path:str, tilde_expand:bool, tilde_val:str) -> str:
286 """Does the opposite of expand_user, with its outputs.
286 """Does the opposite of expand_user, with its outputs.
287 """
287 """
288 if tilde_expand:
288 if tilde_expand:
289 return path.replace(tilde_val, '~')
289 return path.replace(tilde_val, '~')
290 else:
290 else:
291 return path
291 return path
292
292
293
293
294 def completions_sorting_key(word):
294 def completions_sorting_key(word):
295 """key for sorting completions
295 """key for sorting completions
296
296
297 This does several things:
297 This does several things:
298
298
299 - Demote any completions starting with underscores to the end
299 - Demote any completions starting with underscores to the end
300 - Insert any %magic and %%cellmagic completions in the alphabetical order
300 - Insert any %magic and %%cellmagic completions in the alphabetical order
301 by their name
301 by their name
302 """
302 """
303 prio1, prio2 = 0, 0
303 prio1, prio2 = 0, 0
304
304
305 if word.startswith('__'):
305 if word.startswith('__'):
306 prio1 = 2
306 prio1 = 2
307 elif word.startswith('_'):
307 elif word.startswith('_'):
308 prio1 = 1
308 prio1 = 1
309
309
310 if word.endswith('='):
310 if word.endswith('='):
311 prio1 = -1
311 prio1 = -1
312
312
313 if word.startswith('%%'):
313 if word.startswith('%%'):
314 # If there's another % in there, this is something else, so leave it alone
314 # If there's another % in there, this is something else, so leave it alone
315 if not "%" in word[2:]:
315 if not "%" in word[2:]:
316 word = word[2:]
316 word = word[2:]
317 prio2 = 2
317 prio2 = 2
318 elif word.startswith('%'):
318 elif word.startswith('%'):
319 if not "%" in word[1:]:
319 if not "%" in word[1:]:
320 word = word[1:]
320 word = word[1:]
321 prio2 = 1
321 prio2 = 1
322
322
323 return prio1, word, prio2
323 return prio1, word, prio2
324
324
325
325
326 class _FakeJediCompletion:
326 class _FakeJediCompletion:
327 """
327 """
328 This is a workaround to communicate to the UI that Jedi has crashed and to
328 This is a workaround to communicate to the UI that Jedi has crashed and to
329 report a bug. Will be used only id :any:`IPCompleter.debug` is set to true.
329 report a bug. Will be used only id :any:`IPCompleter.debug` is set to true.
330
330
331 Added in IPython 6.0 so should likely be removed for 7.0
331 Added in IPython 6.0 so should likely be removed for 7.0
332
332
333 """
333 """
334
334
335 def __init__(self, name):
335 def __init__(self, name):
336
336
337 self.name = name
337 self.name = name
338 self.complete = name
338 self.complete = name
339 self.type = 'crashed'
339 self.type = 'crashed'
340 self.name_with_symbols = name
340 self.name_with_symbols = name
341 self.signature = ''
341 self.signature = ''
342 self._origin = 'fake'
342 self._origin = 'fake'
343
343
344 def __repr__(self):
344 def __repr__(self):
345 return '<Fake completion object jedi has crashed>'
345 return '<Fake completion object jedi has crashed>'
346
346
347
347
348 class Completion:
348 class Completion:
349 """
349 """
350 Completion object used and return by IPython completers.
350 Completion object used and return by IPython completers.
351
351
352 .. warning:: Unstable
352 .. warning:: Unstable
353
353
354 This function is unstable, API may change without warning.
354 This function is unstable, API may change without warning.
355 It will also raise unless use in proper context manager.
355 It will also raise unless use in proper context manager.
356
356
357 This act as a middle ground :any:`Completion` object between the
357 This act as a middle ground :any:`Completion` object between the
358 :any:`jedi.api.classes.Completion` object and the Prompt Toolkit completion
358 :any:`jedi.api.classes.Completion` object and the Prompt Toolkit completion
359 object. While Jedi need a lot of information about evaluator and how the
359 object. While Jedi need a lot of information about evaluator and how the
360 code should be ran/inspected, PromptToolkit (and other frontend) mostly
360 code should be ran/inspected, PromptToolkit (and other frontend) mostly
361 need user facing information.
361 need user facing information.
362
362
363 - Which range should be replaced replaced by what.
363 - Which range should be replaced replaced by what.
364 - Some metadata (like completion type), or meta information to displayed to
364 - Some metadata (like completion type), or meta information to displayed to
365 the use user.
365 the use user.
366
366
367 For debugging purpose we can also store the origin of the completion (``jedi``,
367 For debugging purpose we can also store the origin of the completion (``jedi``,
368 ``IPython.python_matches``, ``IPython.magics_matches``...).
368 ``IPython.python_matches``, ``IPython.magics_matches``...).
369 """
369 """
370
370
371 __slots__ = ['start', 'end', 'text', 'type', 'signature', '_origin']
371 __slots__ = ['start', 'end', 'text', 'type', 'signature', '_origin']
372
372
373 def __init__(self, start: int, end: int, text: str, *, type: str=None, _origin='', signature='') -> None:
373 def __init__(self, start: int, end: int, text: str, *, type: str=None, _origin='', signature='') -> None:
374 warnings.warn("``Completion`` is a provisional API (as of IPython 6.0). "
374 warnings.warn("``Completion`` is a provisional API (as of IPython 6.0). "
375 "It may change without warnings. "
375 "It may change without warnings. "
376 "Use in corresponding context manager.",
376 "Use in corresponding context manager.",
377 category=ProvisionalCompleterWarning, stacklevel=2)
377 category=ProvisionalCompleterWarning, stacklevel=2)
378
378
379 self.start = start
379 self.start = start
380 self.end = end
380 self.end = end
381 self.text = text
381 self.text = text
382 self.type = type
382 self.type = type
383 self.signature = signature
383 self.signature = signature
384 self._origin = _origin
384 self._origin = _origin
385
385
386 def __repr__(self):
386 def __repr__(self):
387 return '<Completion start=%s end=%s text=%r type=%r, signature=%r,>' % \
387 return '<Completion start=%s end=%s text=%r type=%r, signature=%r,>' % \
388 (self.start, self.end, self.text, self.type or '?', self.signature or '?')
388 (self.start, self.end, self.text, self.type or '?', self.signature or '?')
389
389
390 def __eq__(self, other)->Bool:
390 def __eq__(self, other)->Bool:
391 """
391 """
392 Equality and hash do not hash the type (as some completer may not be
392 Equality and hash do not hash the type (as some completer may not be
393 able to infer the type), but are use to (partially) de-duplicate
393 able to infer the type), but are use to (partially) de-duplicate
394 completion.
394 completion.
395
395
396 Completely de-duplicating completion is a bit tricker that just
396 Completely de-duplicating completion is a bit tricker that just
397 comparing as it depends on surrounding text, which Completions are not
397 comparing as it depends on surrounding text, which Completions are not
398 aware of.
398 aware of.
399 """
399 """
400 return self.start == other.start and \
400 return self.start == other.start and \
401 self.end == other.end and \
401 self.end == other.end and \
402 self.text == other.text
402 self.text == other.text
403
403
404 def __hash__(self):
404 def __hash__(self):
405 return hash((self.start, self.end, self.text))
405 return hash((self.start, self.end, self.text))
406
406
407
407
408 _IC = Iterable[Completion]
408 _IC = Iterable[Completion]
409
409
410
410
411 def _deduplicate_completions(text: str, completions: _IC)-> _IC:
411 def _deduplicate_completions(text: str, completions: _IC)-> _IC:
412 """
412 """
413 Deduplicate a set of completions.
413 Deduplicate a set of completions.
414
414
415 .. warning:: Unstable
415 .. warning:: Unstable
416
416
417 This function is unstable, API may change without warning.
417 This function is unstable, API may change without warning.
418
418
419 Parameters
419 Parameters
420 ----------
420 ----------
421 text: str
421 text: str
422 text that should be completed.
422 text that should be completed.
423 completions: Iterator[Completion]
423 completions: Iterator[Completion]
424 iterator over the completions to deduplicate
424 iterator over the completions to deduplicate
425
425
426 Yields
426 Yields
427 ------
427 ------
428 `Completions` objects
428 `Completions` objects
429
429
430
430
431 Completions coming from multiple sources, may be different but end up having
431 Completions coming from multiple sources, may be different but end up having
432 the same effect when applied to ``text``. If this is the case, this will
432 the same effect when applied to ``text``. If this is the case, this will
433 consider completions as equal and only emit the first encountered.
433 consider completions as equal and only emit the first encountered.
434
434
435 Not folded in `completions()` yet for debugging purpose, and to detect when
435 Not folded in `completions()` yet for debugging purpose, and to detect when
436 the IPython completer does return things that Jedi does not, but should be
436 the IPython completer does return things that Jedi does not, but should be
437 at some point.
437 at some point.
438 """
438 """
439 completions = list(completions)
439 completions = list(completions)
440 if not completions:
440 if not completions:
441 return
441 return
442
442
443 new_start = min(c.start for c in completions)
443 new_start = min(c.start for c in completions)
444 new_end = max(c.end for c in completions)
444 new_end = max(c.end for c in completions)
445
445
446 seen = set()
446 seen = set()
447 for c in completions:
447 for c in completions:
448 new_text = text[new_start:c.start] + c.text + text[c.end:new_end]
448 new_text = text[new_start:c.start] + c.text + text[c.end:new_end]
449 if new_text not in seen:
449 if new_text not in seen:
450 yield c
450 yield c
451 seen.add(new_text)
451 seen.add(new_text)
452
452
453
453
454 def rectify_completions(text: str, completions: _IC, *, _debug=False)->_IC:
454 def rectify_completions(text: str, completions: _IC, *, _debug=False)->_IC:
455 """
455 """
456 Rectify a set of completions to all have the same ``start`` and ``end``
456 Rectify a set of completions to all have the same ``start`` and ``end``
457
457
458 .. warning:: Unstable
458 .. warning:: Unstable
459
459
460 This function is unstable, API may change without warning.
460 This function is unstable, API may change without warning.
461 It will also raise unless use in proper context manager.
461 It will also raise unless use in proper context manager.
462
462
463 Parameters
463 Parameters
464 ----------
464 ----------
465 text: str
465 text: str
466 text that should be completed.
466 text that should be completed.
467 completions: Iterator[Completion]
467 completions: Iterator[Completion]
468 iterator over the completions to rectify
468 iterator over the completions to rectify
469
469
470
470
471 :any:`jedi.api.classes.Completion` s returned by Jedi may not have the same start and end, though
471 :any:`jedi.api.classes.Completion` s returned by Jedi may not have the same start and end, though
472 the Jupyter Protocol requires them to behave like so. This will readjust
472 the Jupyter Protocol requires them to behave like so. This will readjust
473 the completion to have the same ``start`` and ``end`` by padding both
473 the completion to have the same ``start`` and ``end`` by padding both
474 extremities with surrounding text.
474 extremities with surrounding text.
475
475
476 During stabilisation should support a ``_debug`` option to log which
476 During stabilisation should support a ``_debug`` option to log which
477 completion are return by the IPython completer and not found in Jedi in
477 completion are return by the IPython completer and not found in Jedi in
478 order to make upstream bug report.
478 order to make upstream bug report.
479 """
479 """
480 warnings.warn("`rectify_completions` is a provisional API (as of IPython 6.0). "
480 warnings.warn("`rectify_completions` is a provisional API (as of IPython 6.0). "
481 "It may change without warnings. "
481 "It may change without warnings. "
482 "Use in corresponding context manager.",
482 "Use in corresponding context manager.",
483 category=ProvisionalCompleterWarning, stacklevel=2)
483 category=ProvisionalCompleterWarning, stacklevel=2)
484
484
485 completions = list(completions)
485 completions = list(completions)
486 if not completions:
486 if not completions:
487 return
487 return
488 starts = (c.start for c in completions)
488 starts = (c.start for c in completions)
489 ends = (c.end for c in completions)
489 ends = (c.end for c in completions)
490
490
491 new_start = min(starts)
491 new_start = min(starts)
492 new_end = max(ends)
492 new_end = max(ends)
493
493
494 seen_jedi = set()
494 seen_jedi = set()
495 seen_python_matches = set()
495 seen_python_matches = set()
496 for c in completions:
496 for c in completions:
497 new_text = text[new_start:c.start] + c.text + text[c.end:new_end]
497 new_text = text[new_start:c.start] + c.text + text[c.end:new_end]
498 if c._origin == 'jedi':
498 if c._origin == 'jedi':
499 seen_jedi.add(new_text)
499 seen_jedi.add(new_text)
500 elif c._origin == 'IPCompleter.python_matches':
500 elif c._origin == 'IPCompleter.python_matches':
501 seen_python_matches.add(new_text)
501 seen_python_matches.add(new_text)
502 yield Completion(new_start, new_end, new_text, type=c.type, _origin=c._origin, signature=c.signature)
502 yield Completion(new_start, new_end, new_text, type=c.type, _origin=c._origin, signature=c.signature)
503 diff = seen_python_matches.difference(seen_jedi)
503 diff = seen_python_matches.difference(seen_jedi)
504 if diff and _debug:
504 if diff and _debug:
505 print('IPython.python matches have extras:', diff)
505 print('IPython.python matches have extras:', diff)
506
506
507
507
508 if sys.platform == 'win32':
508 if sys.platform == 'win32':
509 DELIMS = ' \t\n`!@#$^&*()=+[{]}|;\'",<>?'
509 DELIMS = ' \t\n`!@#$^&*()=+[{]}|;\'",<>?'
510 else:
510 else:
511 DELIMS = ' \t\n`!@#$^&*()=+[{]}\\|;:\'",<>?'
511 DELIMS = ' \t\n`!@#$^&*()=+[{]}\\|;:\'",<>?'
512
512
513 GREEDY_DELIMS = ' =\r\n'
513 GREEDY_DELIMS = ' =\r\n'
514
514
515
515
516 class CompletionSplitter(object):
516 class CompletionSplitter(object):
517 """An object to split an input line in a manner similar to readline.
517 """An object to split an input line in a manner similar to readline.
518
518
519 By having our own implementation, we can expose readline-like completion in
519 By having our own implementation, we can expose readline-like completion in
520 a uniform manner to all frontends. This object only needs to be given the
520 a uniform manner to all frontends. This object only needs to be given the
521 line of text to be split and the cursor position on said line, and it
521 line of text to be split and the cursor position on said line, and it
522 returns the 'word' to be completed on at the cursor after splitting the
522 returns the 'word' to be completed on at the cursor after splitting the
523 entire line.
523 entire line.
524
524
525 What characters are used as splitting delimiters can be controlled by
525 What characters are used as splitting delimiters can be controlled by
526 setting the ``delims`` attribute (this is a property that internally
526 setting the ``delims`` attribute (this is a property that internally
527 automatically builds the necessary regular expression)"""
527 automatically builds the necessary regular expression)"""
528
528
529 # Private interface
529 # Private interface
530
530
531 # A string of delimiter characters. The default value makes sense for
531 # A string of delimiter characters. The default value makes sense for
532 # IPython's most typical usage patterns.
532 # IPython's most typical usage patterns.
533 _delims = DELIMS
533 _delims = DELIMS
534
534
535 # The expression (a normal string) to be compiled into a regular expression
535 # The expression (a normal string) to be compiled into a regular expression
536 # for actual splitting. We store it as an attribute mostly for ease of
536 # for actual splitting. We store it as an attribute mostly for ease of
537 # debugging, since this type of code can be so tricky to debug.
537 # debugging, since this type of code can be so tricky to debug.
538 _delim_expr = None
538 _delim_expr = None
539
539
540 # The regular expression that does the actual splitting
540 # The regular expression that does the actual splitting
541 _delim_re = None
541 _delim_re = None
542
542
543 def __init__(self, delims=None):
543 def __init__(self, delims=None):
544 delims = CompletionSplitter._delims if delims is None else delims
544 delims = CompletionSplitter._delims if delims is None else delims
545 self.delims = delims
545 self.delims = delims
546
546
547 @property
547 @property
548 def delims(self):
548 def delims(self):
549 """Return the string of delimiter characters."""
549 """Return the string of delimiter characters."""
550 return self._delims
550 return self._delims
551
551
552 @delims.setter
552 @delims.setter
553 def delims(self, delims):
553 def delims(self, delims):
554 """Set the delimiters for line splitting."""
554 """Set the delimiters for line splitting."""
555 expr = '[' + ''.join('\\'+ c for c in delims) + ']'
555 expr = '[' + ''.join('\\'+ c for c in delims) + ']'
556 self._delim_re = re.compile(expr)
556 self._delim_re = re.compile(expr)
557 self._delims = delims
557 self._delims = delims
558 self._delim_expr = expr
558 self._delim_expr = expr
559
559
560 def split_line(self, line, cursor_pos=None):
560 def split_line(self, line, cursor_pos=None):
561 """Split a line of text with a cursor at the given position.
561 """Split a line of text with a cursor at the given position.
562 """
562 """
563 l = line if cursor_pos is None else line[:cursor_pos]
563 l = line if cursor_pos is None else line[:cursor_pos]
564 return self._delim_re.split(l)[-1]
564 return self._delim_re.split(l)[-1]
565
565
566
566
567
567
568 class Completer(Configurable):
568 class Completer(Configurable):
569
569
570 greedy = Bool(False,
570 greedy = Bool(False,
571 help="""Activate greedy completion
571 help="""Activate greedy completion
572 PENDING DEPRECTION. this is now mostly taken care of with Jedi.
572 PENDING DEPRECTION. this is now mostly taken care of with Jedi.
573
573
574 This will enable completion on elements of lists, results of function calls, etc.,
574 This will enable completion on elements of lists, results of function calls, etc.,
575 but can be unsafe because the code is actually evaluated on TAB.
575 but can be unsafe because the code is actually evaluated on TAB.
576 """
576 """
577 ).tag(config=True)
577 ).tag(config=True)
578
578
579 use_jedi = Bool(default_value=False,
579 use_jedi = Bool(default_value=False,
580 help="Experimental: Use Jedi to generate autocompletions. "
580 help="Experimental: Use Jedi to generate autocompletions. "
581 "Off by default.").tag(config=True)
581 "Off by default.").tag(config=True)
582
582
583 jedi_compute_type_timeout = Int(default_value=400,
583 jedi_compute_type_timeout = Int(default_value=400,
584 help="""Experimental: restrict time (in milliseconds) during which Jedi can compute types.
584 help="""Experimental: restrict time (in milliseconds) during which Jedi can compute types.
585 Set to 0 to stop computing types. Non-zero value lower than 100ms may hurt
585 Set to 0 to stop computing types. Non-zero value lower than 100ms may hurt
586 performance by preventing jedi to build its cache.
586 performance by preventing jedi to build its cache.
587 """).tag(config=True)
587 """).tag(config=True)
588
588
589 debug = Bool(default_value=False,
589 debug = Bool(default_value=False,
590 help='Enable debug for the Completer. Mostly print extra '
590 help='Enable debug for the Completer. Mostly print extra '
591 'information for experimental jedi integration.')\
591 'information for experimental jedi integration.')\
592 .tag(config=True)
592 .tag(config=True)
593
593
594 backslash_combining_completions = Bool(True,
594 backslash_combining_completions = Bool(True,
595 help="Enable unicode completions, e.g. \\alpha<tab> . "
595 help="Enable unicode completions, e.g. \\alpha<tab> . "
596 "Includes completion of latex commands, unicode names, and expanding "
596 "Includes completion of latex commands, unicode names, and expanding "
597 "unicode characters back to latex commands.").tag(config=True)
597 "unicode characters back to latex commands.").tag(config=True)
598
598
599
599
600
600
601 def __init__(self, namespace=None, global_namespace=None, **kwargs):
601 def __init__(self, namespace=None, global_namespace=None, **kwargs):
602 """Create a new completer for the command line.
602 """Create a new completer for the command line.
603
603
604 Completer(namespace=ns, global_namespace=ns2) -> completer instance.
604 Completer(namespace=ns, global_namespace=ns2) -> completer instance.
605
605
606 If unspecified, the default namespace where completions are performed
606 If unspecified, the default namespace where completions are performed
607 is __main__ (technically, __main__.__dict__). Namespaces should be
607 is __main__ (technically, __main__.__dict__). Namespaces should be
608 given as dictionaries.
608 given as dictionaries.
609
609
610 An optional second namespace can be given. This allows the completer
610 An optional second namespace can be given. This allows the completer
611 to handle cases where both the local and global scopes need to be
611 to handle cases where both the local and global scopes need to be
612 distinguished.
612 distinguished.
613 """
613 """
614
614
615 # Don't bind to namespace quite yet, but flag whether the user wants a
615 # Don't bind to namespace quite yet, but flag whether the user wants a
616 # specific namespace or to use __main__.__dict__. This will allow us
616 # specific namespace or to use __main__.__dict__. This will allow us
617 # to bind to __main__.__dict__ at completion time, not now.
617 # to bind to __main__.__dict__ at completion time, not now.
618 if namespace is None:
618 if namespace is None:
619 self.use_main_ns = True
619 self.use_main_ns = True
620 else:
620 else:
621 self.use_main_ns = False
621 self.use_main_ns = False
622 self.namespace = namespace
622 self.namespace = namespace
623
623
624 # The global namespace, if given, can be bound directly
624 # The global namespace, if given, can be bound directly
625 if global_namespace is None:
625 if global_namespace is None:
626 self.global_namespace = {}
626 self.global_namespace = {}
627 else:
627 else:
628 self.global_namespace = global_namespace
628 self.global_namespace = global_namespace
629
629
630 super(Completer, self).__init__(**kwargs)
630 super(Completer, self).__init__(**kwargs)
631
631
632 def complete(self, text, state):
632 def complete(self, text, state):
633 """Return the next possible completion for 'text'.
633 """Return the next possible completion for 'text'.
634
634
635 This is called successively with state == 0, 1, 2, ... until it
635 This is called successively with state == 0, 1, 2, ... until it
636 returns None. The completion should begin with 'text'.
636 returns None. The completion should begin with 'text'.
637
637
638 """
638 """
639 if self.use_main_ns:
639 if self.use_main_ns:
640 self.namespace = __main__.__dict__
640 self.namespace = __main__.__dict__
641
641
642 if state == 0:
642 if state == 0:
643 if "." in text:
643 if "." in text:
644 self.matches = self.attr_matches(text)
644 self.matches = self.attr_matches(text)
645 else:
645 else:
646 self.matches = self.global_matches(text)
646 self.matches = self.global_matches(text)
647 try:
647 try:
648 return self.matches[state]
648 return self.matches[state]
649 except IndexError:
649 except IndexError:
650 return None
650 return None
651
651
652 def global_matches(self, text):
652 def global_matches(self, text):
653 """Compute matches when text is a simple name.
653 """Compute matches when text is a simple name.
654
654
655 Return a list of all keywords, built-in functions and names currently
655 Return a list of all keywords, built-in functions and names currently
656 defined in self.namespace or self.global_namespace that match.
656 defined in self.namespace or self.global_namespace that match.
657
657
658 """
658 """
659 matches = []
659 matches = []
660 match_append = matches.append
660 match_append = matches.append
661 n = len(text)
661 n = len(text)
662 for lst in [keyword.kwlist,
662 for lst in [keyword.kwlist,
663 builtin_mod.__dict__.keys(),
663 builtin_mod.__dict__.keys(),
664 self.namespace.keys(),
664 self.namespace.keys(),
665 self.global_namespace.keys()]:
665 self.global_namespace.keys()]:
666 for word in lst:
666 for word in lst:
667 if word[:n] == text and word != "__builtins__":
667 if word[:n] == text and word != "__builtins__":
668 match_append(word)
668 match_append(word)
669
669
670 snake_case_re = re.compile(r"[^_]+(_[^_]+)+?\Z")
670 snake_case_re = re.compile(r"[^_]+(_[^_]+)+?\Z")
671 for lst in [self.namespace.keys(),
671 for lst in [self.namespace.keys(),
672 self.global_namespace.keys()]:
672 self.global_namespace.keys()]:
673 shortened = {"_".join([sub[0] for sub in word.split('_')]) : word
673 shortened = {"_".join([sub[0] for sub in word.split('_')]) : word
674 for word in lst if snake_case_re.match(word)}
674 for word in lst if snake_case_re.match(word)}
675 for word in shortened.keys():
675 for word in shortened.keys():
676 if word[:n] == text and word != "__builtins__":
676 if word[:n] == text and word != "__builtins__":
677 match_append(shortened[word])
677 match_append(shortened[word])
678 return matches
678 return matches
679
679
680 def attr_matches(self, text):
680 def attr_matches(self, text):
681 """Compute matches when text contains a dot.
681 """Compute matches when text contains a dot.
682
682
683 Assuming the text is of the form NAME.NAME....[NAME], and is
683 Assuming the text is of the form NAME.NAME....[NAME], and is
684 evaluatable in self.namespace or self.global_namespace, it will be
684 evaluatable in self.namespace or self.global_namespace, it will be
685 evaluated and its attributes (as revealed by dir()) are used as
685 evaluated and its attributes (as revealed by dir()) are used as
686 possible completions. (For class instances, class members are
686 possible completions. (For class instances, class members are
687 also considered.)
687 also considered.)
688
688
689 WARNING: this can still invoke arbitrary C code, if an object
689 WARNING: this can still invoke arbitrary C code, if an object
690 with a __getattr__ hook is evaluated.
690 with a __getattr__ hook is evaluated.
691
691
692 """
692 """
693
693
694 # Another option, seems to work great. Catches things like ''.<tab>
694 # Another option, seems to work great. Catches things like ''.<tab>
695 m = re.match(r"(\S+(\.\w+)*)\.(\w*)$", text)
695 m = re.match(r"(\S+(\.\w+)*)\.(\w*)$", text)
696
696
697 if m:
697 if m:
698 expr, attr = m.group(1, 3)
698 expr, attr = m.group(1, 3)
699 elif self.greedy:
699 elif self.greedy:
700 m2 = re.match(r"(.+)\.(\w*)$", self.line_buffer)
700 m2 = re.match(r"(.+)\.(\w*)$", self.line_buffer)
701 if not m2:
701 if not m2:
702 return []
702 return []
703 expr, attr = m2.group(1,2)
703 expr, attr = m2.group(1,2)
704 else:
704 else:
705 return []
705 return []
706
706
707 try:
707 try:
708 obj = eval(expr, self.namespace)
708 obj = eval(expr, self.namespace)
709 except:
709 except:
710 try:
710 try:
711 obj = eval(expr, self.global_namespace)
711 obj = eval(expr, self.global_namespace)
712 except:
712 except:
713 return []
713 return []
714
714
715 if self.limit_to__all__ and hasattr(obj, '__all__'):
715 if self.limit_to__all__ and hasattr(obj, '__all__'):
716 words = get__all__entries(obj)
716 words = get__all__entries(obj)
717 else:
717 else:
718 words = dir2(obj)
718 words = dir2(obj)
719
719
720 try:
720 try:
721 words = generics.complete_object(obj, words)
721 words = generics.complete_object(obj, words)
722 except TryNext:
722 except TryNext:
723 pass
723 pass
724 except AssertionError:
724 except AssertionError:
725 raise
725 raise
726 except Exception:
726 except Exception:
727 # Silence errors from completion function
727 # Silence errors from completion function
728 #raise # dbg
728 #raise # dbg
729 pass
729 pass
730 # Build match list to return
730 # Build match list to return
731 n = len(attr)
731 n = len(attr)
732 return [u"%s.%s" % (expr, w) for w in words if w[:n] == attr ]
732 return [u"%s.%s" % (expr, w) for w in words if w[:n] == attr ]
733
733
734
734
735 def get__all__entries(obj):
735 def get__all__entries(obj):
736 """returns the strings in the __all__ attribute"""
736 """returns the strings in the __all__ attribute"""
737 try:
737 try:
738 words = getattr(obj, '__all__')
738 words = getattr(obj, '__all__')
739 except:
739 except:
740 return []
740 return []
741
741
742 return [w for w in words if isinstance(w, str)]
742 return [w for w in words if isinstance(w, str)]
743
743
744
744
745 def match_dict_keys(keys: List[str], prefix: str, delims: str):
745 def match_dict_keys(keys: List[str], prefix: str, delims: str):
746 """Used by dict_key_matches, matching the prefix to a list of keys
746 """Used by dict_key_matches, matching the prefix to a list of keys
747
747
748 Parameters
748 Parameters
749 ==========
749 ==========
750 keys:
750 keys:
751 list of keys in dictionary currently being completed.
751 list of keys in dictionary currently being completed.
752 prefix:
752 prefix:
753 Part of the text already typed by the user. e.g. `mydict[b'fo`
753 Part of the text already typed by the user. e.g. `mydict[b'fo`
754 delims:
754 delims:
755 String of delimiters to consider when finding the current key.
755 String of delimiters to consider when finding the current key.
756
756
757 Returns
757 Returns
758 =======
758 =======
759
759
760 A tuple of three elements: ``quote``, ``token_start``, ``matched``, with
760 A tuple of three elements: ``quote``, ``token_start``, ``matched``, with
761 ``quote`` being the quote that need to be used to close current string.
761 ``quote`` being the quote that need to be used to close current string.
762 ``token_start`` the position where the replacement should start occurring,
762 ``token_start`` the position where the replacement should start occurring,
763 ``matches`` a list of replacement/completion
763 ``matches`` a list of replacement/completion
764
764
765 """
765 """
766 if not prefix:
766 if not prefix:
767 return None, 0, [repr(k) for k in keys
767 return None, 0, [repr(k) for k in keys
768 if isinstance(k, (str, bytes))]
768 if isinstance(k, (str, bytes))]
769 quote_match = re.search('["\']', prefix)
769 quote_match = re.search('["\']', prefix)
770 quote = quote_match.group()
770 quote = quote_match.group()
771 try:
771 try:
772 prefix_str = eval(prefix + quote, {})
772 prefix_str = eval(prefix + quote, {})
773 except Exception:
773 except Exception:
774 return None, 0, []
774 return None, 0, []
775
775
776 pattern = '[^' + ''.join('\\' + c for c in delims) + ']*$'
776 pattern = '[^' + ''.join('\\' + c for c in delims) + ']*$'
777 token_match = re.search(pattern, prefix, re.UNICODE)
777 token_match = re.search(pattern, prefix, re.UNICODE)
778 token_start = token_match.start()
778 token_start = token_match.start()
779 token_prefix = token_match.group()
779 token_prefix = token_match.group()
780
780
781 matched = []
781 matched = []
782 for key in keys:
782 for key in keys:
783 try:
783 try:
784 if not key.startswith(prefix_str):
784 if not key.startswith(prefix_str):
785 continue
785 continue
786 except (AttributeError, TypeError, UnicodeError):
786 except (AttributeError, TypeError, UnicodeError):
787 # Python 3+ TypeError on b'a'.startswith('a') or vice-versa
787 # Python 3+ TypeError on b'a'.startswith('a') or vice-versa
788 continue
788 continue
789
789
790 # reformat remainder of key to begin with prefix
790 # reformat remainder of key to begin with prefix
791 rem = key[len(prefix_str):]
791 rem = key[len(prefix_str):]
792 # force repr wrapped in '
792 # force repr wrapped in '
793 rem_repr = repr(rem + '"') if isinstance(rem, str) else repr(rem + b'"')
793 rem_repr = repr(rem + '"') if isinstance(rem, str) else repr(rem + b'"')
794 if rem_repr.startswith('u') and prefix[0] not in 'uU':
794 if rem_repr.startswith('u') and prefix[0] not in 'uU':
795 # Found key is unicode, but prefix is Py2 string.
795 # Found key is unicode, but prefix is Py2 string.
796 # Therefore attempt to interpret key as string.
796 # Therefore attempt to interpret key as string.
797 try:
797 try:
798 rem_repr = repr(rem.encode('ascii') + '"')
798 rem_repr = repr(rem.encode('ascii') + '"')
799 except UnicodeEncodeError:
799 except UnicodeEncodeError:
800 continue
800 continue
801
801
802 rem_repr = rem_repr[1 + rem_repr.index("'"):-2]
802 rem_repr = rem_repr[1 + rem_repr.index("'"):-2]
803 if quote == '"':
803 if quote == '"':
804 # The entered prefix is quoted with ",
804 # The entered prefix is quoted with ",
805 # but the match is quoted with '.
805 # but the match is quoted with '.
806 # A contained " hence needs escaping for comparison:
806 # A contained " hence needs escaping for comparison:
807 rem_repr = rem_repr.replace('"', '\\"')
807 rem_repr = rem_repr.replace('"', '\\"')
808
808
809 # then reinsert prefix from start of token
809 # then reinsert prefix from start of token
810 matched.append('%s%s' % (token_prefix, rem_repr))
810 matched.append('%s%s' % (token_prefix, rem_repr))
811 return quote, token_start, matched
811 return quote, token_start, matched
812
812
813
813
814 def cursor_to_position(text:str, line:int, column:int)->int:
814 def cursor_to_position(text:str, line:int, column:int)->int:
815 """
815 """
816
816
817 Convert the (line,column) position of the cursor in text to an offset in a
817 Convert the (line,column) position of the cursor in text to an offset in a
818 string.
818 string.
819
819
820 Parameters
820 Parameters
821 ----------
821 ----------
822
822
823 text : str
823 text : str
824 The text in which to calculate the cursor offset
824 The text in which to calculate the cursor offset
825 line : int
825 line : int
826 Line of the cursor; 0-indexed
826 Line of the cursor; 0-indexed
827 column : int
827 column : int
828 Column of the cursor 0-indexed
828 Column of the cursor 0-indexed
829
829
830 Return
830 Return
831 ------
831 ------
832 Position of the cursor in ``text``, 0-indexed.
832 Position of the cursor in ``text``, 0-indexed.
833
833
834 See Also
834 See Also
835 --------
835 --------
836 position_to_cursor: reciprocal of this function
836 position_to_cursor: reciprocal of this function
837
837
838 """
838 """
839 lines = text.split('\n')
839 lines = text.split('\n')
840 assert line <= len(lines), '{} <= {}'.format(str(line), str(len(lines)))
840 assert line <= len(lines), '{} <= {}'.format(str(line), str(len(lines)))
841
841
842 return sum(len(l) + 1 for l in lines[:line]) + column
842 return sum(len(l) + 1 for l in lines[:line]) + column
843
843
844 def position_to_cursor(text:str, offset:int)->Tuple[int, int]:
844 def position_to_cursor(text:str, offset:int)->Tuple[int, int]:
845 """
845 """
846 Convert the position of the cursor in text (0 indexed) to a line
846 Convert the position of the cursor in text (0 indexed) to a line
847 number(0-indexed) and a column number (0-indexed) pair
847 number(0-indexed) and a column number (0-indexed) pair
848
848
849 Position should be a valid position in ``text``.
849 Position should be a valid position in ``text``.
850
850
851 Parameters
851 Parameters
852 ----------
852 ----------
853
853
854 text : str
854 text : str
855 The text in which to calculate the cursor offset
855 The text in which to calculate the cursor offset
856 offset : int
856 offset : int
857 Position of the cursor in ``text``, 0-indexed.
857 Position of the cursor in ``text``, 0-indexed.
858
858
859 Return
859 Return
860 ------
860 ------
861 (line, column) : (int, int)
861 (line, column) : (int, int)
862 Line of the cursor; 0-indexed, column of the cursor 0-indexed
862 Line of the cursor; 0-indexed, column of the cursor 0-indexed
863
863
864
864
865 See Also
865 See Also
866 --------
866 --------
867 cursor_to_position : reciprocal of this function
867 cursor_to_position : reciprocal of this function
868
868
869
869
870 """
870 """
871
871
872 assert 0 <= offset <= len(text) , "0 <= %s <= %s" % (offset , len(text))
872 assert 0 <= offset <= len(text) , "0 <= %s <= %s" % (offset , len(text))
873
873
874 before = text[:offset]
874 before = text[:offset]
875 blines = before.split('\n') # ! splitnes trim trailing \n
875 blines = before.split('\n') # ! splitnes trim trailing \n
876 line = before.count('\n')
876 line = before.count('\n')
877 col = len(blines[-1])
877 col = len(blines[-1])
878 return line, col
878 return line, col
879
879
880
880
881 def _safe_isinstance(obj, module, class_name):
881 def _safe_isinstance(obj, module, class_name):
882 """Checks if obj is an instance of module.class_name if loaded
882 """Checks if obj is an instance of module.class_name if loaded
883 """
883 """
884 return (module in sys.modules and
884 return (module in sys.modules and
885 isinstance(obj, getattr(import_module(module), class_name)))
885 isinstance(obj, getattr(import_module(module), class_name)))
886
886
887
887
888 def back_unicode_name_matches(text):
888 def back_unicode_name_matches(text):
889 u"""Match unicode characters back to unicode name
889 u"""Match unicode characters back to unicode name
890
890
891 This does ``☃`` -> ``\\snowman``
891 This does ``☃`` -> ``\\snowman``
892
892
893 Note that snowman is not a valid python3 combining character but will be expanded.
893 Note that snowman is not a valid python3 combining character but will be expanded.
894 Though it will not recombine back to the snowman character by the completion machinery.
894 Though it will not recombine back to the snowman character by the completion machinery.
895
895
896 This will not either back-complete standard sequences like \\n, \\b ...
896 This will not either back-complete standard sequences like \\n, \\b ...
897
897
898 Used on Python 3 only.
898 Used on Python 3 only.
899 """
899 """
900 if len(text)<2:
900 if len(text)<2:
901 return u'', ()
901 return u'', ()
902 maybe_slash = text[-2]
902 maybe_slash = text[-2]
903 if maybe_slash != '\\':
903 if maybe_slash != '\\':
904 return u'', ()
904 return u'', ()
905
905
906 char = text[-1]
906 char = text[-1]
907 # no expand on quote for completion in strings.
907 # no expand on quote for completion in strings.
908 # nor backcomplete standard ascii keys
908 # nor backcomplete standard ascii keys
909 if char in string.ascii_letters or char in ['"',"'"]:
909 if char in string.ascii_letters or char in ['"',"'"]:
910 return u'', ()
910 return u'', ()
911 try :
911 try :
912 unic = unicodedata.name(char)
912 unic = unicodedata.name(char)
913 return '\\'+char,['\\'+unic]
913 return '\\'+char,['\\'+unic]
914 except KeyError:
914 except KeyError:
915 pass
915 pass
916 return u'', ()
916 return u'', ()
917
917
918 def back_latex_name_matches(text:str):
918 def back_latex_name_matches(text:str):
919 """Match latex characters back to unicode name
919 """Match latex characters back to unicode name
920
920
921 This does ``\\ℵ`` -> ``\\aleph``
921 This does ``\\ℵ`` -> ``\\aleph``
922
922
923 Used on Python 3 only.
923 Used on Python 3 only.
924 """
924 """
925 if len(text)<2:
925 if len(text)<2:
926 return u'', ()
926 return u'', ()
927 maybe_slash = text[-2]
927 maybe_slash = text[-2]
928 if maybe_slash != '\\':
928 if maybe_slash != '\\':
929 return u'', ()
929 return u'', ()
930
930
931
931
932 char = text[-1]
932 char = text[-1]
933 # no expand on quote for completion in strings.
933 # no expand on quote for completion in strings.
934 # nor backcomplete standard ascii keys
934 # nor backcomplete standard ascii keys
935 if char in string.ascii_letters or char in ['"',"'"]:
935 if char in string.ascii_letters or char in ['"',"'"]:
936 return u'', ()
936 return u'', ()
937 try :
937 try :
938 latex = reverse_latex_symbol[char]
938 latex = reverse_latex_symbol[char]
939 # '\\' replace the \ as well
939 # '\\' replace the \ as well
940 return '\\'+char,[latex]
940 return '\\'+char,[latex]
941 except KeyError:
941 except KeyError:
942 pass
942 pass
943 return u'', ()
943 return u'', ()
944
944
945
945
946 def _formatparamchildren(parameter) -> str:
946 def _formatparamchildren(parameter) -> str:
947 """
947 """
948 Get parameter name and value from Jedi Private API
948 Get parameter name and value from Jedi Private API
949
949
950 Jedi does not expose a simple way to get `param=value` from its API.
950 Jedi does not expose a simple way to get `param=value` from its API.
951
951
952 Parameter
952 Parameter
953 =========
953 =========
954
954
955 parameter:
955 parameter:
956 Jedi's function `Param`
956 Jedi's function `Param`
957
957
958 Returns
958 Returns
959 =======
959 =======
960
960
961 A string like 'a', 'b=1', '*args', '**kwargs'
961 A string like 'a', 'b=1', '*args', '**kwargs'
962
962
963
963
964 """
964 """
965 description = parameter.description
965 description = parameter.description
966 if not description.startswith('param '):
966 if not description.startswith('param '):
967 raise ValueError('Jedi function parameter description have change format.'
967 raise ValueError('Jedi function parameter description have change format.'
968 'Expected "param ...", found %r".' % description)
968 'Expected "param ...", found %r".' % description)
969 return description[6:]
969 return description[6:]
970
970
971 def _make_signature(completion)-> str:
971 def _make_signature(completion)-> str:
972 """
972 """
973 Make the signature from a jedi completion
973 Make the signature from a jedi completion
974
974
975 Parameter
975 Parameter
976 =========
976 =========
977
977
978 completion: jedi.Completion
978 completion: jedi.Completion
979 object does not complete a function type
979 object does not complete a function type
980
980
981 Returns
981 Returns
982 =======
982 =======
983
983
984 a string consisting of the function signature, with the parenthesis but
984 a string consisting of the function signature, with the parenthesis but
985 without the function name. example:
985 without the function name. example:
986 `(a, *args, b=1, **kwargs)`
986 `(a, *args, b=1, **kwargs)`
987
987
988 """
988 """
989
989
990 return '(%s)'% ', '.join([f for f in (_formatparamchildren(p) for p in completion.params) if f])
990 return '(%s)'% ', '.join([f for f in (_formatparamchildren(p) for p in completion.params) if f])
991
991
992 class IPCompleter(Completer):
992 class IPCompleter(Completer):
993 """Extension of the completer class with IPython-specific features"""
993 """Extension of the completer class with IPython-specific features"""
994
994
995 @observe('greedy')
995 @observe('greedy')
996 def _greedy_changed(self, change):
996 def _greedy_changed(self, change):
997 """update the splitter and readline delims when greedy is changed"""
997 """update the splitter and readline delims when greedy is changed"""
998 if change['new']:
998 if change['new']:
999 self.splitter.delims = GREEDY_DELIMS
999 self.splitter.delims = GREEDY_DELIMS
1000 else:
1000 else:
1001 self.splitter.delims = DELIMS
1001 self.splitter.delims = DELIMS
1002
1002
1003 merge_completions = Bool(True,
1003 merge_completions = Bool(True,
1004 help="""Whether to merge completion results into a single list
1004 help="""Whether to merge completion results into a single list
1005
1005
1006 If False, only the completion results from the first non-empty
1006 If False, only the completion results from the first non-empty
1007 completer will be returned.
1007 completer will be returned.
1008 """
1008 """
1009 ).tag(config=True)
1009 ).tag(config=True)
1010 omit__names = Enum((0,1,2), default_value=2,
1010 omit__names = Enum((0,1,2), default_value=2,
1011 help="""Instruct the completer to omit private method names
1011 help="""Instruct the completer to omit private method names
1012
1012
1013 Specifically, when completing on ``object.<tab>``.
1013 Specifically, when completing on ``object.<tab>``.
1014
1014
1015 When 2 [default]: all names that start with '_' will be excluded.
1015 When 2 [default]: all names that start with '_' will be excluded.
1016
1016
1017 When 1: all 'magic' names (``__foo__``) will be excluded.
1017 When 1: all 'magic' names (``__foo__``) will be excluded.
1018
1018
1019 When 0: nothing will be excluded.
1019 When 0: nothing will be excluded.
1020 """
1020 """
1021 ).tag(config=True)
1021 ).tag(config=True)
1022 limit_to__all__ = Bool(False,
1022 limit_to__all__ = Bool(False,
1023 help="""
1023 help="""
1024 DEPRECATED as of version 5.0.
1024 DEPRECATED as of version 5.0.
1025
1025
1026 Instruct the completer to use __all__ for the completion
1026 Instruct the completer to use __all__ for the completion
1027
1027
1028 Specifically, when completing on ``object.<tab>``.
1028 Specifically, when completing on ``object.<tab>``.
1029
1029
1030 When True: only those names in obj.__all__ will be included.
1030 When True: only those names in obj.__all__ will be included.
1031
1031
1032 When False [default]: the __all__ attribute is ignored
1032 When False [default]: the __all__ attribute is ignored
1033 """,
1033 """,
1034 ).tag(config=True)
1034 ).tag(config=True)
1035
1035
1036 @observe('limit_to__all__')
1036 @observe('limit_to__all__')
1037 def _limit_to_all_changed(self, change):
1037 def _limit_to_all_changed(self, change):
1038 warnings.warn('`IPython.core.IPCompleter.limit_to__all__` configuration '
1038 warnings.warn('`IPython.core.IPCompleter.limit_to__all__` configuration '
1039 'value has been deprecated since IPython 5.0, will be made to have '
1039 'value has been deprecated since IPython 5.0, will be made to have '
1040 'no effects and then removed in future version of IPython.',
1040 'no effects and then removed in future version of IPython.',
1041 UserWarning)
1041 UserWarning)
1042
1042
1043 def __init__(self, shell=None, namespace=None, global_namespace=None,
1043 def __init__(self, shell=None, namespace=None, global_namespace=None,
1044 use_readline=_deprecation_readline_sentinel, config=None, **kwargs):
1044 use_readline=_deprecation_readline_sentinel, config=None, **kwargs):
1045 """IPCompleter() -> completer
1045 """IPCompleter() -> completer
1046
1046
1047 Return a completer object.
1047 Return a completer object.
1048
1048
1049 Parameters
1049 Parameters
1050 ----------
1050 ----------
1051
1051
1052 shell
1052 shell
1053 a pointer to the ipython shell itself. This is needed
1053 a pointer to the ipython shell itself. This is needed
1054 because this completer knows about magic functions, and those can
1054 because this completer knows about magic functions, and those can
1055 only be accessed via the ipython instance.
1055 only be accessed via the ipython instance.
1056
1056
1057 namespace : dict, optional
1057 namespace : dict, optional
1058 an optional dict where completions are performed.
1058 an optional dict where completions are performed.
1059
1059
1060 global_namespace : dict, optional
1060 global_namespace : dict, optional
1061 secondary optional dict for completions, to
1061 secondary optional dict for completions, to
1062 handle cases (such as IPython embedded inside functions) where
1062 handle cases (such as IPython embedded inside functions) where
1063 both Python scopes are visible.
1063 both Python scopes are visible.
1064
1064
1065 use_readline : bool, optional
1065 use_readline : bool, optional
1066 DEPRECATED, ignored since IPython 6.0, will have no effects
1066 DEPRECATED, ignored since IPython 6.0, will have no effects
1067 """
1067 """
1068
1068
1069 self.magic_escape = ESC_MAGIC
1069 self.magic_escape = ESC_MAGIC
1070 self.splitter = CompletionSplitter()
1070 self.splitter = CompletionSplitter()
1071
1071
1072 if use_readline is not _deprecation_readline_sentinel:
1072 if use_readline is not _deprecation_readline_sentinel:
1073 warnings.warn('The `use_readline` parameter is deprecated and ignored since IPython 6.0.',
1073 warnings.warn('The `use_readline` parameter is deprecated and ignored since IPython 6.0.',
1074 DeprecationWarning, stacklevel=2)
1074 DeprecationWarning, stacklevel=2)
1075
1075
1076 # _greedy_changed() depends on splitter and readline being defined:
1076 # _greedy_changed() depends on splitter and readline being defined:
1077 Completer.__init__(self, namespace=namespace, global_namespace=global_namespace,
1077 Completer.__init__(self, namespace=namespace, global_namespace=global_namespace,
1078 config=config, **kwargs)
1078 config=config, **kwargs)
1079
1079
1080 # List where completion matches will be stored
1080 # List where completion matches will be stored
1081 self.matches = []
1081 self.matches = []
1082 self.shell = shell
1082 self.shell = shell
1083 # Regexp to split filenames with spaces in them
1083 # Regexp to split filenames with spaces in them
1084 self.space_name_re = re.compile(r'([^\\] )')
1084 self.space_name_re = re.compile(r'([^\\] )')
1085 # Hold a local ref. to glob.glob for speed
1085 # Hold a local ref. to glob.glob for speed
1086 self.glob = glob.glob
1086 self.glob = glob.glob
1087
1087
1088 # Determine if we are running on 'dumb' terminals, like (X)Emacs
1088 # Determine if we are running on 'dumb' terminals, like (X)Emacs
1089 # buffers, to avoid completion problems.
1089 # buffers, to avoid completion problems.
1090 term = os.environ.get('TERM','xterm')
1090 term = os.environ.get('TERM','xterm')
1091 self.dumb_terminal = term in ['dumb','emacs']
1091 self.dumb_terminal = term in ['dumb','emacs']
1092
1092
1093 # Special handling of backslashes needed in win32 platforms
1093 # Special handling of backslashes needed in win32 platforms
1094 if sys.platform == "win32":
1094 if sys.platform == "win32":
1095 self.clean_glob = self._clean_glob_win32
1095 self.clean_glob = self._clean_glob_win32
1096 else:
1096 else:
1097 self.clean_glob = self._clean_glob
1097 self.clean_glob = self._clean_glob
1098
1098
1099 #regexp to parse docstring for function signature
1099 #regexp to parse docstring for function signature
1100 self.docstring_sig_re = re.compile(r'^[\w|\s.]+\(([^)]*)\).*')
1100 self.docstring_sig_re = re.compile(r'^[\w|\s.]+\(([^)]*)\).*')
1101 self.docstring_kwd_re = re.compile(r'[\s|\[]*(\w+)(?:\s*=\s*.*)')
1101 self.docstring_kwd_re = re.compile(r'[\s|\[]*(\w+)(?:\s*=\s*.*)')
1102 #use this if positional argument name is also needed
1102 #use this if positional argument name is also needed
1103 #= re.compile(r'[\s|\[]*(\w+)(?:\s*=?\s*.*)')
1103 #= re.compile(r'[\s|\[]*(\w+)(?:\s*=?\s*.*)')
1104
1104
1105 self.magic_arg_matchers = [
1105 self.magic_arg_matchers = [
1106 self.magic_config_matches,
1106 self.magic_config_matches,
1107 self.magic_color_matches,
1107 self.magic_color_matches,
1108 ]
1108 ]
1109
1109
1110 # This is set externally by InteractiveShell
1110 # This is set externally by InteractiveShell
1111 self.custom_completers = None
1111 self.custom_completers = None
1112
1112
1113 @property
1113 @property
1114 def matchers(self):
1114 def matchers(self):
1115 """All active matcher routines for completion"""
1115 """All active matcher routines for completion"""
1116 if self.use_jedi:
1116 if self.use_jedi:
1117 return [
1117 return [
1118 self.file_matches,
1118 self.file_matches,
1119 self.magic_matches,
1119 self.magic_matches,
1120 self.dict_key_matches,
1120 self.dict_key_matches,
1121 ]
1121 ]
1122 else:
1122 else:
1123 return [
1123 return [
1124 self.python_matches,
1124 self.python_matches,
1125 self.file_matches,
1125 self.file_matches,
1126 self.magic_matches,
1126 self.magic_matches,
1127 self.python_func_kw_matches,
1127 self.python_func_kw_matches,
1128 self.dict_key_matches,
1128 self.dict_key_matches,
1129 ]
1129 ]
1130
1130
1131 def all_completions(self, text):
1131 def all_completions(self, text):
1132 """
1132 """
1133 Wrapper around the complete method for the benefit of emacs.
1133 Wrapper around the complete method for the benefit of emacs.
1134 """
1134 """
1135 return self.complete(text)[1]
1135 return self.complete(text)[1]
1136
1136
1137 def _clean_glob(self, text):
1137 def _clean_glob(self, text):
1138 return self.glob("%s*" % text)
1138 return self.glob("%s*" % text)
1139
1139
1140 def _clean_glob_win32(self,text):
1140 def _clean_glob_win32(self,text):
1141 return [f.replace("\\","/")
1141 return [f.replace("\\","/")
1142 for f in self.glob("%s*" % text)]
1142 for f in self.glob("%s*" % text)]
1143
1143
1144 def file_matches(self, text):
1144 def file_matches(self, text):
1145 """Match filenames, expanding ~USER type strings.
1145 """Match filenames, expanding ~USER type strings.
1146
1146
1147 Most of the seemingly convoluted logic in this completer is an
1147 Most of the seemingly convoluted logic in this completer is an
1148 attempt to handle filenames with spaces in them. And yet it's not
1148 attempt to handle filenames with spaces in them. And yet it's not
1149 quite perfect, because Python's readline doesn't expose all of the
1149 quite perfect, because Python's readline doesn't expose all of the
1150 GNU readline details needed for this to be done correctly.
1150 GNU readline details needed for this to be done correctly.
1151
1151
1152 For a filename with a space in it, the printed completions will be
1152 For a filename with a space in it, the printed completions will be
1153 only the parts after what's already been typed (instead of the
1153 only the parts after what's already been typed (instead of the
1154 full completions, as is normally done). I don't think with the
1154 full completions, as is normally done). I don't think with the
1155 current (as of Python 2.3) Python readline it's possible to do
1155 current (as of Python 2.3) Python readline it's possible to do
1156 better."""
1156 better."""
1157
1157
1158 # chars that require escaping with backslash - i.e. chars
1158 # chars that require escaping with backslash - i.e. chars
1159 # that readline treats incorrectly as delimiters, but we
1159 # that readline treats incorrectly as delimiters, but we
1160 # don't want to treat as delimiters in filename matching
1160 # don't want to treat as delimiters in filename matching
1161 # when escaped with backslash
1161 # when escaped with backslash
1162 if text.startswith('!'):
1162 if text.startswith('!'):
1163 text = text[1:]
1163 text = text[1:]
1164 text_prefix = u'!'
1164 text_prefix = u'!'
1165 else:
1165 else:
1166 text_prefix = u''
1166 text_prefix = u''
1167
1167
1168 text_until_cursor = self.text_until_cursor
1168 text_until_cursor = self.text_until_cursor
1169 # track strings with open quotes
1169 # track strings with open quotes
1170 open_quotes = has_open_quotes(text_until_cursor)
1170 open_quotes = has_open_quotes(text_until_cursor)
1171
1171
1172 if '(' in text_until_cursor or '[' in text_until_cursor:
1172 if '(' in text_until_cursor or '[' in text_until_cursor:
1173 lsplit = text
1173 lsplit = text
1174 else:
1174 else:
1175 try:
1175 try:
1176 # arg_split ~ shlex.split, but with unicode bugs fixed by us
1176 # arg_split ~ shlex.split, but with unicode bugs fixed by us
1177 lsplit = arg_split(text_until_cursor)[-1]
1177 lsplit = arg_split(text_until_cursor)[-1]
1178 except ValueError:
1178 except ValueError:
1179 # typically an unmatched ", or backslash without escaped char.
1179 # typically an unmatched ", or backslash without escaped char.
1180 if open_quotes:
1180 if open_quotes:
1181 lsplit = text_until_cursor.split(open_quotes)[-1]
1181 lsplit = text_until_cursor.split(open_quotes)[-1]
1182 else:
1182 else:
1183 return []
1183 return []
1184 except IndexError:
1184 except IndexError:
1185 # tab pressed on empty line
1185 # tab pressed on empty line
1186 lsplit = ""
1186 lsplit = ""
1187
1187
1188 if not open_quotes and lsplit != protect_filename(lsplit):
1188 if not open_quotes and lsplit != protect_filename(lsplit):
1189 # if protectables are found, do matching on the whole escaped name
1189 # if protectables are found, do matching on the whole escaped name
1190 has_protectables = True
1190 has_protectables = True
1191 text0,text = text,lsplit
1191 text0,text = text,lsplit
1192 else:
1192 else:
1193 has_protectables = False
1193 has_protectables = False
1194 text = os.path.expanduser(text)
1194 text = os.path.expanduser(text)
1195
1195
1196 if text == "":
1196 if text == "":
1197 return [text_prefix + protect_filename(f) for f in self.glob("*")]
1197 return [text_prefix + protect_filename(f) for f in self.glob("*")]
1198
1198
1199 # Compute the matches from the filesystem
1199 # Compute the matches from the filesystem
1200 if sys.platform == 'win32':
1200 if sys.platform == 'win32':
1201 m0 = self.clean_glob(text)
1201 m0 = self.clean_glob(text)
1202 else:
1202 else:
1203 m0 = self.clean_glob(text.replace('\\', ''))
1203 m0 = self.clean_glob(text.replace('\\', ''))
1204
1204
1205 if has_protectables:
1205 if has_protectables:
1206 # If we had protectables, we need to revert our changes to the
1206 # If we had protectables, we need to revert our changes to the
1207 # beginning of filename so that we don't double-write the part
1207 # beginning of filename so that we don't double-write the part
1208 # of the filename we have so far
1208 # of the filename we have so far
1209 len_lsplit = len(lsplit)
1209 len_lsplit = len(lsplit)
1210 matches = [text_prefix + text0 +
1210 matches = [text_prefix + text0 +
1211 protect_filename(f[len_lsplit:]) for f in m0]
1211 protect_filename(f[len_lsplit:]) for f in m0]
1212 else:
1212 else:
1213 if open_quotes:
1213 if open_quotes:
1214 # if we have a string with an open quote, we don't need to
1214 # if we have a string with an open quote, we don't need to
1215 # protect the names beyond the quote (and we _shouldn't_, as
1215 # protect the names beyond the quote (and we _shouldn't_, as
1216 # it would cause bugs when the filesystem call is made).
1216 # it would cause bugs when the filesystem call is made).
1217 matches = m0 if sys.platform == "win32" else\
1217 matches = m0 if sys.platform == "win32" else\
1218 [protect_filename(f, open_quotes) for f in m0]
1218 [protect_filename(f, open_quotes) for f in m0]
1219 else:
1219 else:
1220 matches = [text_prefix +
1220 matches = [text_prefix +
1221 protect_filename(f) for f in m0]
1221 protect_filename(f) for f in m0]
1222
1222
1223 # Mark directories in input list by appending '/' to their names.
1223 # Mark directories in input list by appending '/' to their names.
1224 return [x+'/' if os.path.isdir(x) else x for x in matches]
1224 return [x+'/' if os.path.isdir(x) else x for x in matches]
1225
1225
1226 def magic_matches(self, text):
1226 def magic_matches(self, text):
1227 """Match magics"""
1227 """Match magics"""
1228 # Get all shell magics now rather than statically, so magics loaded at
1228 # Get all shell magics now rather than statically, so magics loaded at
1229 # runtime show up too.
1229 # runtime show up too.
1230 lsm = self.shell.magics_manager.lsmagic()
1230 lsm = self.shell.magics_manager.lsmagic()
1231 line_magics = lsm['line']
1231 line_magics = lsm['line']
1232 cell_magics = lsm['cell']
1232 cell_magics = lsm['cell']
1233 pre = self.magic_escape
1233 pre = self.magic_escape
1234 pre2 = pre+pre
1234 pre2 = pre+pre
1235
1235
1236 explicit_magic = text.startswith(pre)
1236 explicit_magic = text.startswith(pre)
1237
1237
1238 # Completion logic:
1238 # Completion logic:
1239 # - user gives %%: only do cell magics
1239 # - user gives %%: only do cell magics
1240 # - user gives %: do both line and cell magics
1240 # - user gives %: do both line and cell magics
1241 # - no prefix: do both
1241 # - no prefix: do both
1242 # In other words, line magics are skipped if the user gives %% explicitly
1242 # In other words, line magics are skipped if the user gives %% explicitly
1243 #
1243 #
1244 # We also exclude magics that match any currently visible names:
1244 # We also exclude magics that match any currently visible names:
1245 # https://github.com/ipython/ipython/issues/4877, unless the user has
1245 # https://github.com/ipython/ipython/issues/4877, unless the user has
1246 # typed a %:
1246 # typed a %:
1247 # https://github.com/ipython/ipython/issues/10754
1247 # https://github.com/ipython/ipython/issues/10754
1248 bare_text = text.lstrip(pre)
1248 bare_text = text.lstrip(pre)
1249 global_matches = self.global_matches(bare_text)
1249 global_matches = self.global_matches(bare_text)
1250 if not explicit_magic:
1250 if not explicit_magic:
1251 def matches(magic):
1251 def matches(magic):
1252 """
1252 """
1253 Filter magics, in particular remove magics that match
1253 Filter magics, in particular remove magics that match
1254 a name present in global namespace.
1254 a name present in global namespace.
1255 """
1255 """
1256 return ( magic.startswith(bare_text) and
1256 return ( magic.startswith(bare_text) and
1257 magic not in global_matches )
1257 magic not in global_matches )
1258 else:
1258 else:
1259 def matches(magic):
1259 def matches(magic):
1260 return magic.startswith(bare_text)
1260 return magic.startswith(bare_text)
1261
1261
1262 comp = [ pre2+m for m in cell_magics if matches(m)]
1262 comp = [ pre2+m for m in cell_magics if matches(m)]
1263 if not text.startswith(pre2):
1263 if not text.startswith(pre2):
1264 comp += [ pre+m for m in line_magics if matches(m)]
1264 comp += [ pre+m for m in line_magics if matches(m)]
1265
1265
1266 return comp
1266 return comp
1267
1267
1268 def magic_config_matches(self, text:str) -> List[str]:
1268 def magic_config_matches(self, text:str) -> List[str]:
1269 """ Match class names and attributes for %config magic """
1269 """ Match class names and attributes for %config magic """
1270 texts = text.strip().split()
1270 texts = text.strip().split()
1271
1271
1272 if len(texts) > 0 and (texts[0] == 'config' or texts[0] == '%config'):
1272 if len(texts) > 0 and (texts[0] == 'config' or texts[0] == '%config'):
1273 # get all configuration classes
1273 # get all configuration classes
1274 classes = sorted(set([ c for c in self.shell.configurables
1274 classes = sorted(set([ c for c in self.shell.configurables
1275 if c.__class__.class_traits(config=True)
1275 if c.__class__.class_traits(config=True)
1276 ]), key=lambda x: x.__class__.__name__)
1276 ]), key=lambda x: x.__class__.__name__)
1277 classnames = [ c.__class__.__name__ for c in classes ]
1277 classnames = [ c.__class__.__name__ for c in classes ]
1278
1278
1279 # return all classnames if config or %config is given
1279 # return all classnames if config or %config is given
1280 if len(texts) == 1:
1280 if len(texts) == 1:
1281 return classnames
1281 return classnames
1282
1282
1283 # match classname
1283 # match classname
1284 classname_texts = texts[1].split('.')
1284 classname_texts = texts[1].split('.')
1285 classname = classname_texts[0]
1285 classname = classname_texts[0]
1286 classname_matches = [ c for c in classnames
1286 classname_matches = [ c for c in classnames
1287 if c.startswith(classname) ]
1287 if c.startswith(classname) ]
1288
1288
1289 # return matched classes or the matched class with attributes
1289 # return matched classes or the matched class with attributes
1290 if texts[1].find('.') < 0:
1290 if texts[1].find('.') < 0:
1291 return classname_matches
1291 return classname_matches
1292 elif len(classname_matches) == 1 and \
1292 elif len(classname_matches) == 1 and \
1293 classname_matches[0] == classname:
1293 classname_matches[0] == classname:
1294 cls = classes[classnames.index(classname)].__class__
1294 cls = classes[classnames.index(classname)].__class__
1295 help = cls.class_get_help()
1295 help = cls.class_get_help()
1296 # strip leading '--' from cl-args:
1296 # strip leading '--' from cl-args:
1297 help = re.sub(re.compile(r'^--', re.MULTILINE), '', help)
1297 help = re.sub(re.compile(r'^--', re.MULTILINE), '', help)
1298 return [ attr.split('=')[0]
1298 return [ attr.split('=')[0]
1299 for attr in help.strip().splitlines()
1299 for attr in help.strip().splitlines()
1300 if attr.startswith(texts[1]) ]
1300 if attr.startswith(texts[1]) ]
1301 return []
1301 return []
1302
1302
1303 def magic_color_matches(self, text:str) -> List[str] :
1303 def magic_color_matches(self, text:str) -> List[str] :
1304 """ Match color schemes for %colors magic"""
1304 """ Match color schemes for %colors magic"""
1305 texts = text.split()
1305 texts = text.split()
1306 if text.endswith(' '):
1306 if text.endswith(' '):
1307 # .split() strips off the trailing whitespace. Add '' back
1307 # .split() strips off the trailing whitespace. Add '' back
1308 # so that: '%colors ' -> ['%colors', '']
1308 # so that: '%colors ' -> ['%colors', '']
1309 texts.append('')
1309 texts.append('')
1310
1310
1311 if len(texts) == 2 and (texts[0] == 'colors' or texts[0] == '%colors'):
1311 if len(texts) == 2 and (texts[0] == 'colors' or texts[0] == '%colors'):
1312 prefix = texts[1]
1312 prefix = texts[1]
1313 return [ color for color in InspectColors.keys()
1313 return [ color for color in InspectColors.keys()
1314 if color.startswith(prefix) ]
1314 if color.startswith(prefix) ]
1315 return []
1315 return []
1316
1316
1317 def _jedi_matches(self, cursor_column:int, cursor_line:int, text:str):
1317 def _jedi_matches(self, cursor_column:int, cursor_line:int, text:str):
1318 """
1318 """
1319
1319
1320 Return a list of :any:`jedi.api.Completions` object from a ``text`` and
1320 Return a list of :any:`jedi.api.Completions` object from a ``text`` and
1321 cursor position.
1321 cursor position.
1322
1322
1323 Parameters
1323 Parameters
1324 ----------
1324 ----------
1325 cursor_column : int
1325 cursor_column : int
1326 column position of the cursor in ``text``, 0-indexed.
1326 column position of the cursor in ``text``, 0-indexed.
1327 cursor_line : int
1327 cursor_line : int
1328 line position of the cursor in ``text``, 0-indexed
1328 line position of the cursor in ``text``, 0-indexed
1329 text : str
1329 text : str
1330 text to complete
1330 text to complete
1331
1331
1332 Debugging
1332 Debugging
1333 ---------
1333 ---------
1334
1334
1335 If ``IPCompleter.debug`` is ``True`` may return a :any:`_FakeJediCompletion`
1335 If ``IPCompleter.debug`` is ``True`` may return a :any:`_FakeJediCompletion`
1336 object containing a string with the Jedi debug information attached.
1336 object containing a string with the Jedi debug information attached.
1337 """
1337 """
1338 namespaces = [self.namespace]
1338 namespaces = [self.namespace]
1339 if self.global_namespace is not None:
1339 if self.global_namespace is not None:
1340 namespaces.append(self.global_namespace)
1340 namespaces.append(self.global_namespace)
1341
1341
1342 completion_filter = lambda x:x
1342 completion_filter = lambda x:x
1343 offset = cursor_to_position(text, cursor_line, cursor_column)
1343 offset = cursor_to_position(text, cursor_line, cursor_column)
1344 # filter output if we are completing for object members
1344 # filter output if we are completing for object members
1345 if offset:
1345 if offset:
1346 pre = text[offset-1]
1346 pre = text[offset-1]
1347 if pre == '.':
1347 if pre == '.':
1348 if self.omit__names == 2:
1348 if self.omit__names == 2:
1349 completion_filter = lambda c:not c.name.startswith('_')
1349 completion_filter = lambda c:not c.name.startswith('_')
1350 elif self.omit__names == 1:
1350 elif self.omit__names == 1:
1351 completion_filter = lambda c:not (c.name.startswith('__') and c.name.endswith('__'))
1351 completion_filter = lambda c:not (c.name.startswith('__') and c.name.endswith('__'))
1352 elif self.omit__names == 0:
1352 elif self.omit__names == 0:
1353 completion_filter = lambda x:x
1353 completion_filter = lambda x:x
1354 else:
1354 else:
1355 raise ValueError("Don't understand self.omit__names == {}".format(self.omit__names))
1355 raise ValueError("Don't understand self.omit__names == {}".format(self.omit__names))
1356
1356
1357 interpreter = jedi.Interpreter(
1357 interpreter = jedi.Interpreter(
1358 text[:offset], namespaces, column=cursor_column, line=cursor_line + 1)
1358 text[:offset], namespaces, column=cursor_column, line=cursor_line + 1)
1359 try_jedi = True
1359 try_jedi = True
1360
1360
1361 try:
1361 try:
1362 # should we check the type of the node is Error ?
1362 # should we check the type of the node is Error ?
1363 try:
1363 try:
1364 # jedi < 0.11
1364 # jedi < 0.11
1365 from jedi.parser.tree import ErrorLeaf
1365 from jedi.parser.tree import ErrorLeaf
1366 except ImportError:
1366 except ImportError:
1367 # jedi >= 0.11
1367 # jedi >= 0.11
1368 from parso.tree import ErrorLeaf
1368 from parso.tree import ErrorLeaf
1369
1369
1370 next_to_last_tree = interpreter._get_module().tree_node.children[-2]
1370 next_to_last_tree = interpreter._get_module().tree_node.children[-2]
1371 completing_string = False
1371 completing_string = False
1372 if isinstance(next_to_last_tree, ErrorLeaf):
1372 if isinstance(next_to_last_tree, ErrorLeaf):
1373 completing_string = next_to_last_tree.value.lstrip()[0] in {'"', "'"}
1373 completing_string = next_to_last_tree.value.lstrip()[0] in {'"', "'"}
1374 # if we are in a string jedi is likely not the right candidate for
1374 # if we are in a string jedi is likely not the right candidate for
1375 # now. Skip it.
1375 # now. Skip it.
1376 try_jedi = not completing_string
1376 try_jedi = not completing_string
1377 except Exception as e:
1377 except Exception as e:
1378 # many of things can go wrong, we are using private API just don't crash.
1378 # many of things can go wrong, we are using private API just don't crash.
1379 if self.debug:
1379 if self.debug:
1380 print("Error detecting if completing a non-finished string :", e, '|')
1380 print("Error detecting if completing a non-finished string :", e, '|')
1381
1381
1382 if not try_jedi:
1382 if not try_jedi:
1383 return []
1383 return []
1384 try:
1384 try:
1385 return filter(completion_filter, interpreter.completions())
1385 return filter(completion_filter, interpreter.completions())
1386 except Exception as e:
1386 except Exception as e:
1387 if self.debug:
1387 if self.debug:
1388 return [_FakeJediCompletion('Oops Jedi has crashed, please report a bug with the following:\n"""\n%s\ns"""' % (e))]
1388 return [_FakeJediCompletion('Oops Jedi has crashed, please report a bug with the following:\n"""\n%s\ns"""' % (e))]
1389 else:
1389 else:
1390 return []
1390 return []
1391
1391
1392 def python_matches(self, text):
1392 def python_matches(self, text):
1393 """Match attributes or global python names"""
1393 """Match attributes or global python names"""
1394 if "." in text:
1394 if "." in text:
1395 try:
1395 try:
1396 matches = self.attr_matches(text)
1396 matches = self.attr_matches(text)
1397 if text.endswith('.') and self.omit__names:
1397 if text.endswith('.') and self.omit__names:
1398 if self.omit__names == 1:
1398 if self.omit__names == 1:
1399 # true if txt is _not_ a __ name, false otherwise:
1399 # true if txt is _not_ a __ name, false otherwise:
1400 no__name = (lambda txt:
1400 no__name = (lambda txt:
1401 re.match(r'.*\.__.*?__',txt) is None)
1401 re.match(r'.*\.__.*?__',txt) is None)
1402 else:
1402 else:
1403 # true if txt is _not_ a _ name, false otherwise:
1403 # true if txt is _not_ a _ name, false otherwise:
1404 no__name = (lambda txt:
1404 no__name = (lambda txt:
1405 re.match(r'\._.*?',txt[txt.rindex('.'):]) is None)
1405 re.match(r'\._.*?',txt[txt.rindex('.'):]) is None)
1406 matches = filter(no__name, matches)
1406 matches = filter(no__name, matches)
1407 except NameError:
1407 except NameError:
1408 # catches <undefined attributes>.<tab>
1408 # catches <undefined attributes>.<tab>
1409 matches = []
1409 matches = []
1410 else:
1410 else:
1411 matches = self.global_matches(text)
1411 matches = self.global_matches(text)
1412 return matches
1412 return matches
1413
1413
1414 def _default_arguments_from_docstring(self, doc):
1414 def _default_arguments_from_docstring(self, doc):
1415 """Parse the first line of docstring for call signature.
1415 """Parse the first line of docstring for call signature.
1416
1416
1417 Docstring should be of the form 'min(iterable[, key=func])\n'.
1417 Docstring should be of the form 'min(iterable[, key=func])\n'.
1418 It can also parse cython docstring of the form
1418 It can also parse cython docstring of the form
1419 'Minuit.migrad(self, int ncall=10000, resume=True, int nsplit=1)'.
1419 'Minuit.migrad(self, int ncall=10000, resume=True, int nsplit=1)'.
1420 """
1420 """
1421 if doc is None:
1421 if doc is None:
1422 return []
1422 return []
1423
1423
1424 #care only the firstline
1424 #care only the firstline
1425 line = doc.lstrip().splitlines()[0]
1425 line = doc.lstrip().splitlines()[0]
1426
1426
1427 #p = re.compile(r'^[\w|\s.]+\(([^)]*)\).*')
1427 #p = re.compile(r'^[\w|\s.]+\(([^)]*)\).*')
1428 #'min(iterable[, key=func])\n' -> 'iterable[, key=func]'
1428 #'min(iterable[, key=func])\n' -> 'iterable[, key=func]'
1429 sig = self.docstring_sig_re.search(line)
1429 sig = self.docstring_sig_re.search(line)
1430 if sig is None:
1430 if sig is None:
1431 return []
1431 return []
1432 # iterable[, key=func]' -> ['iterable[' ,' key=func]']
1432 # iterable[, key=func]' -> ['iterable[' ,' key=func]']
1433 sig = sig.groups()[0].split(',')
1433 sig = sig.groups()[0].split(',')
1434 ret = []
1434 ret = []
1435 for s in sig:
1435 for s in sig:
1436 #re.compile(r'[\s|\[]*(\w+)(?:\s*=\s*.*)')
1436 #re.compile(r'[\s|\[]*(\w+)(?:\s*=\s*.*)')
1437 ret += self.docstring_kwd_re.findall(s)
1437 ret += self.docstring_kwd_re.findall(s)
1438 return ret
1438 return ret
1439
1439
1440 def _default_arguments(self, obj):
1440 def _default_arguments(self, obj):
1441 """Return the list of default arguments of obj if it is callable,
1441 """Return the list of default arguments of obj if it is callable,
1442 or empty list otherwise."""
1442 or empty list otherwise."""
1443 call_obj = obj
1443 call_obj = obj
1444 ret = []
1444 ret = []
1445 if inspect.isbuiltin(obj):
1445 if inspect.isbuiltin(obj):
1446 pass
1446 pass
1447 elif not (inspect.isfunction(obj) or inspect.ismethod(obj)):
1447 elif not (inspect.isfunction(obj) or inspect.ismethod(obj)):
1448 if inspect.isclass(obj):
1448 if inspect.isclass(obj):
1449 #for cython embedsignature=True the constructor docstring
1449 #for cython embedsignature=True the constructor docstring
1450 #belongs to the object itself not __init__
1450 #belongs to the object itself not __init__
1451 ret += self._default_arguments_from_docstring(
1451 ret += self._default_arguments_from_docstring(
1452 getattr(obj, '__doc__', ''))
1452 getattr(obj, '__doc__', ''))
1453 # for classes, check for __init__,__new__
1453 # for classes, check for __init__,__new__
1454 call_obj = (getattr(obj, '__init__', None) or
1454 call_obj = (getattr(obj, '__init__', None) or
1455 getattr(obj, '__new__', None))
1455 getattr(obj, '__new__', None))
1456 # for all others, check if they are __call__able
1456 # for all others, check if they are __call__able
1457 elif hasattr(obj, '__call__'):
1457 elif hasattr(obj, '__call__'):
1458 call_obj = obj.__call__
1458 call_obj = obj.__call__
1459 ret += self._default_arguments_from_docstring(
1459 ret += self._default_arguments_from_docstring(
1460 getattr(call_obj, '__doc__', ''))
1460 getattr(call_obj, '__doc__', ''))
1461
1461
1462 _keeps = (inspect.Parameter.KEYWORD_ONLY,
1462 _keeps = (inspect.Parameter.KEYWORD_ONLY,
1463 inspect.Parameter.POSITIONAL_OR_KEYWORD)
1463 inspect.Parameter.POSITIONAL_OR_KEYWORD)
1464
1464
1465 try:
1465 try:
1466 sig = inspect.signature(call_obj)
1466 sig = inspect.signature(call_obj)
1467 ret.extend(k for k, v in sig.parameters.items() if
1467 ret.extend(k for k, v in sig.parameters.items() if
1468 v.kind in _keeps)
1468 v.kind in _keeps)
1469 except ValueError:
1469 except ValueError:
1470 pass
1470 pass
1471
1471
1472 return list(set(ret))
1472 return list(set(ret))
1473
1473
1474 def python_func_kw_matches(self,text):
1474 def python_func_kw_matches(self,text):
1475 """Match named parameters (kwargs) of the last open function"""
1475 """Match named parameters (kwargs) of the last open function"""
1476
1476
1477 if "." in text: # a parameter cannot be dotted
1477 if "." in text: # a parameter cannot be dotted
1478 return []
1478 return []
1479 try: regexp = self.__funcParamsRegex
1479 try: regexp = self.__funcParamsRegex
1480 except AttributeError:
1480 except AttributeError:
1481 regexp = self.__funcParamsRegex = re.compile(r'''
1481 regexp = self.__funcParamsRegex = re.compile(r'''
1482 '.*?(?<!\\)' | # single quoted strings or
1482 '.*?(?<!\\)' | # single quoted strings or
1483 ".*?(?<!\\)" | # double quoted strings or
1483 ".*?(?<!\\)" | # double quoted strings or
1484 \w+ | # identifier
1484 \w+ | # identifier
1485 \S # other characters
1485 \S # other characters
1486 ''', re.VERBOSE | re.DOTALL)
1486 ''', re.VERBOSE | re.DOTALL)
1487 # 1. find the nearest identifier that comes before an unclosed
1487 # 1. find the nearest identifier that comes before an unclosed
1488 # parenthesis before the cursor
1488 # parenthesis before the cursor
1489 # e.g. for "foo (1+bar(x), pa<cursor>,a=1)", the candidate is "foo"
1489 # e.g. for "foo (1+bar(x), pa<cursor>,a=1)", the candidate is "foo"
1490 tokens = regexp.findall(self.text_until_cursor)
1490 tokens = regexp.findall(self.text_until_cursor)
1491 iterTokens = reversed(tokens); openPar = 0
1491 iterTokens = reversed(tokens); openPar = 0
1492
1492
1493 for token in iterTokens:
1493 for token in iterTokens:
1494 if token == ')':
1494 if token == ')':
1495 openPar -= 1
1495 openPar -= 1
1496 elif token == '(':
1496 elif token == '(':
1497 openPar += 1
1497 openPar += 1
1498 if openPar > 0:
1498 if openPar > 0:
1499 # found the last unclosed parenthesis
1499 # found the last unclosed parenthesis
1500 break
1500 break
1501 else:
1501 else:
1502 return []
1502 return []
1503 # 2. Concatenate dotted names ("foo.bar" for "foo.bar(x, pa" )
1503 # 2. Concatenate dotted names ("foo.bar" for "foo.bar(x, pa" )
1504 ids = []
1504 ids = []
1505 isId = re.compile(r'\w+$').match
1505 isId = re.compile(r'\w+$').match
1506
1506
1507 while True:
1507 while True:
1508 try:
1508 try:
1509 ids.append(next(iterTokens))
1509 ids.append(next(iterTokens))
1510 if not isId(ids[-1]):
1510 if not isId(ids[-1]):
1511 ids.pop(); break
1511 ids.pop(); break
1512 if not next(iterTokens) == '.':
1512 if not next(iterTokens) == '.':
1513 break
1513 break
1514 except StopIteration:
1514 except StopIteration:
1515 break
1515 break
1516
1516
1517 # Find all named arguments already assigned to, as to avoid suggesting
1517 # Find all named arguments already assigned to, as to avoid suggesting
1518 # them again
1518 # them again
1519 usedNamedArgs = set()
1519 usedNamedArgs = set()
1520 par_level = -1
1520 par_level = -1
1521 for token, next_token in zip(tokens, tokens[1:]):
1521 for token, next_token in zip(tokens, tokens[1:]):
1522 if token == '(':
1522 if token == '(':
1523 par_level += 1
1523 par_level += 1
1524 elif token == ')':
1524 elif token == ')':
1525 par_level -= 1
1525 par_level -= 1
1526
1526
1527 if par_level != 0:
1527 if par_level != 0:
1528 continue
1528 continue
1529
1529
1530 if next_token != '=':
1530 if next_token != '=':
1531 continue
1531 continue
1532
1532
1533 usedNamedArgs.add(token)
1533 usedNamedArgs.add(token)
1534
1534
1535 # lookup the candidate callable matches either using global_matches
1535 # lookup the candidate callable matches either using global_matches
1536 # or attr_matches for dotted names
1536 # or attr_matches for dotted names
1537 if len(ids) == 1:
1537 if len(ids) == 1:
1538 callableMatches = self.global_matches(ids[0])
1538 callableMatches = self.global_matches(ids[0])
1539 else:
1539 else:
1540 callableMatches = self.attr_matches('.'.join(ids[::-1]))
1540 callableMatches = self.attr_matches('.'.join(ids[::-1]))
1541 argMatches = []
1541 argMatches = []
1542 for callableMatch in callableMatches:
1542 for callableMatch in callableMatches:
1543 try:
1543 try:
1544 namedArgs = self._default_arguments(eval(callableMatch,
1544 namedArgs = self._default_arguments(eval(callableMatch,
1545 self.namespace))
1545 self.namespace))
1546 except:
1546 except:
1547 continue
1547 continue
1548
1548
1549 # Remove used named arguments from the list, no need to show twice
1549 # Remove used named arguments from the list, no need to show twice
1550 for namedArg in set(namedArgs) - usedNamedArgs:
1550 for namedArg in set(namedArgs) - usedNamedArgs:
1551 if namedArg.startswith(text):
1551 if namedArg.startswith(text):
1552 argMatches.append(u"%s=" %namedArg)
1552 argMatches.append(u"%s=" %namedArg)
1553 return argMatches
1553 return argMatches
1554
1554
1555 def dict_key_matches(self, text):
1555 def dict_key_matches(self, text):
1556 "Match string keys in a dictionary, after e.g. 'foo[' "
1556 "Match string keys in a dictionary, after e.g. 'foo[' "
1557 def get_keys(obj):
1557 def get_keys(obj):
1558 # Objects can define their own completions by defining an
1558 # Objects can define their own completions by defining an
1559 # _ipy_key_completions_() method.
1559 # _ipy_key_completions_() method.
1560 method = get_real_method(obj, '_ipython_key_completions_')
1560 method = get_real_method(obj, '_ipython_key_completions_')
1561 if method is not None:
1561 if method is not None:
1562 return method()
1562 return method()
1563
1563
1564 # Special case some common in-memory dict-like types
1564 # Special case some common in-memory dict-like types
1565 if isinstance(obj, dict) or\
1565 if isinstance(obj, dict) or\
1566 _safe_isinstance(obj, 'pandas', 'DataFrame'):
1566 _safe_isinstance(obj, 'pandas', 'DataFrame'):
1567 try:
1567 try:
1568 return list(obj.keys())
1568 return list(obj.keys())
1569 except Exception:
1569 except Exception:
1570 return []
1570 return []
1571 elif _safe_isinstance(obj, 'numpy', 'ndarray') or\
1571 elif _safe_isinstance(obj, 'numpy', 'ndarray') or\
1572 _safe_isinstance(obj, 'numpy', 'void'):
1572 _safe_isinstance(obj, 'numpy', 'void'):
1573 return obj.dtype.names or []
1573 return obj.dtype.names or []
1574 return []
1574 return []
1575
1575
1576 try:
1576 try:
1577 regexps = self.__dict_key_regexps
1577 regexps = self.__dict_key_regexps
1578 except AttributeError:
1578 except AttributeError:
1579 dict_key_re_fmt = r'''(?x)
1579 dict_key_re_fmt = r'''(?x)
1580 ( # match dict-referring expression wrt greedy setting
1580 ( # match dict-referring expression wrt greedy setting
1581 %s
1581 %s
1582 )
1582 )
1583 \[ # open bracket
1583 \[ # open bracket
1584 \s* # and optional whitespace
1584 \s* # and optional whitespace
1585 ([uUbB]? # string prefix (r not handled)
1585 ([uUbB]? # string prefix (r not handled)
1586 (?: # unclosed string
1586 (?: # unclosed string
1587 '(?:[^']|(?<!\\)\\')*
1587 '(?:[^']|(?<!\\)\\')*
1588 |
1588 |
1589 "(?:[^"]|(?<!\\)\\")*
1589 "(?:[^"]|(?<!\\)\\")*
1590 )
1590 )
1591 )?
1591 )?
1592 $
1592 $
1593 '''
1593 '''
1594 regexps = self.__dict_key_regexps = {
1594 regexps = self.__dict_key_regexps = {
1595 False: re.compile(dict_key_re_fmt % '''
1595 False: re.compile(dict_key_re_fmt % r'''
1596 # identifiers separated by .
1596 # identifiers separated by .
1597 (?!\d)\w+
1597 (?!\d)\w+
1598 (?:\.(?!\d)\w+)*
1598 (?:\.(?!\d)\w+)*
1599 '''),
1599 '''),
1600 True: re.compile(dict_key_re_fmt % '''
1600 True: re.compile(dict_key_re_fmt % '''
1601 .+
1601 .+
1602 ''')
1602 ''')
1603 }
1603 }
1604
1604
1605 match = regexps[self.greedy].search(self.text_until_cursor)
1605 match = regexps[self.greedy].search(self.text_until_cursor)
1606 if match is None:
1606 if match is None:
1607 return []
1607 return []
1608
1608
1609 expr, prefix = match.groups()
1609 expr, prefix = match.groups()
1610 try:
1610 try:
1611 obj = eval(expr, self.namespace)
1611 obj = eval(expr, self.namespace)
1612 except Exception:
1612 except Exception:
1613 try:
1613 try:
1614 obj = eval(expr, self.global_namespace)
1614 obj = eval(expr, self.global_namespace)
1615 except Exception:
1615 except Exception:
1616 return []
1616 return []
1617
1617
1618 keys = get_keys(obj)
1618 keys = get_keys(obj)
1619 if not keys:
1619 if not keys:
1620 return keys
1620 return keys
1621 closing_quote, token_offset, matches = match_dict_keys(keys, prefix, self.splitter.delims)
1621 closing_quote, token_offset, matches = match_dict_keys(keys, prefix, self.splitter.delims)
1622 if not matches:
1622 if not matches:
1623 return matches
1623 return matches
1624
1624
1625 # get the cursor position of
1625 # get the cursor position of
1626 # - the text being completed
1626 # - the text being completed
1627 # - the start of the key text
1627 # - the start of the key text
1628 # - the start of the completion
1628 # - the start of the completion
1629 text_start = len(self.text_until_cursor) - len(text)
1629 text_start = len(self.text_until_cursor) - len(text)
1630 if prefix:
1630 if prefix:
1631 key_start = match.start(2)
1631 key_start = match.start(2)
1632 completion_start = key_start + token_offset
1632 completion_start = key_start + token_offset
1633 else:
1633 else:
1634 key_start = completion_start = match.end()
1634 key_start = completion_start = match.end()
1635
1635
1636 # grab the leading prefix, to make sure all completions start with `text`
1636 # grab the leading prefix, to make sure all completions start with `text`
1637 if text_start > key_start:
1637 if text_start > key_start:
1638 leading = ''
1638 leading = ''
1639 else:
1639 else:
1640 leading = text[text_start:completion_start]
1640 leading = text[text_start:completion_start]
1641
1641
1642 # the index of the `[` character
1642 # the index of the `[` character
1643 bracket_idx = match.end(1)
1643 bracket_idx = match.end(1)
1644
1644
1645 # append closing quote and bracket as appropriate
1645 # append closing quote and bracket as appropriate
1646 # this is *not* appropriate if the opening quote or bracket is outside
1646 # this is *not* appropriate if the opening quote or bracket is outside
1647 # the text given to this method
1647 # the text given to this method
1648 suf = ''
1648 suf = ''
1649 continuation = self.line_buffer[len(self.text_until_cursor):]
1649 continuation = self.line_buffer[len(self.text_until_cursor):]
1650 if key_start > text_start and closing_quote:
1650 if key_start > text_start and closing_quote:
1651 # quotes were opened inside text, maybe close them
1651 # quotes were opened inside text, maybe close them
1652 if continuation.startswith(closing_quote):
1652 if continuation.startswith(closing_quote):
1653 continuation = continuation[len(closing_quote):]
1653 continuation = continuation[len(closing_quote):]
1654 else:
1654 else:
1655 suf += closing_quote
1655 suf += closing_quote
1656 if bracket_idx > text_start:
1656 if bracket_idx > text_start:
1657 # brackets were opened inside text, maybe close them
1657 # brackets were opened inside text, maybe close them
1658 if not continuation.startswith(']'):
1658 if not continuation.startswith(']'):
1659 suf += ']'
1659 suf += ']'
1660
1660
1661 return [leading + k + suf for k in matches]
1661 return [leading + k + suf for k in matches]
1662
1662
1663 def unicode_name_matches(self, text):
1663 def unicode_name_matches(self, text):
1664 u"""Match Latex-like syntax for unicode characters base
1664 u"""Match Latex-like syntax for unicode characters base
1665 on the name of the character.
1665 on the name of the character.
1666
1666
1667 This does ``\\GREEK SMALL LETTER ETA`` -> ``η``
1667 This does ``\\GREEK SMALL LETTER ETA`` -> ``η``
1668
1668
1669 Works only on valid python 3 identifier, or on combining characters that
1669 Works only on valid python 3 identifier, or on combining characters that
1670 will combine to form a valid identifier.
1670 will combine to form a valid identifier.
1671
1671
1672 Used on Python 3 only.
1672 Used on Python 3 only.
1673 """
1673 """
1674 slashpos = text.rfind('\\')
1674 slashpos = text.rfind('\\')
1675 if slashpos > -1:
1675 if slashpos > -1:
1676 s = text[slashpos+1:]
1676 s = text[slashpos+1:]
1677 try :
1677 try :
1678 unic = unicodedata.lookup(s)
1678 unic = unicodedata.lookup(s)
1679 # allow combining chars
1679 # allow combining chars
1680 if ('a'+unic).isidentifier():
1680 if ('a'+unic).isidentifier():
1681 return '\\'+s,[unic]
1681 return '\\'+s,[unic]
1682 except KeyError:
1682 except KeyError:
1683 pass
1683 pass
1684 return u'', []
1684 return u'', []
1685
1685
1686
1686
1687 def latex_matches(self, text):
1687 def latex_matches(self, text):
1688 u"""Match Latex syntax for unicode characters.
1688 u"""Match Latex syntax for unicode characters.
1689
1689
1690 This does both ``\\alp`` -> ``\\alpha`` and ``\\alpha`` -> ``α``
1690 This does both ``\\alp`` -> ``\\alpha`` and ``\\alpha`` -> ``α``
1691
1691
1692 Used on Python 3 only.
1692 Used on Python 3 only.
1693 """
1693 """
1694 slashpos = text.rfind('\\')
1694 slashpos = text.rfind('\\')
1695 if slashpos > -1:
1695 if slashpos > -1:
1696 s = text[slashpos:]
1696 s = text[slashpos:]
1697 if s in latex_symbols:
1697 if s in latex_symbols:
1698 # Try to complete a full latex symbol to unicode
1698 # Try to complete a full latex symbol to unicode
1699 # \\alpha -> α
1699 # \\alpha -> α
1700 return s, [latex_symbols[s]]
1700 return s, [latex_symbols[s]]
1701 else:
1701 else:
1702 # If a user has partially typed a latex symbol, give them
1702 # If a user has partially typed a latex symbol, give them
1703 # a full list of options \al -> [\aleph, \alpha]
1703 # a full list of options \al -> [\aleph, \alpha]
1704 matches = [k for k in latex_symbols if k.startswith(s)]
1704 matches = [k for k in latex_symbols if k.startswith(s)]
1705 return s, matches
1705 return s, matches
1706 return u'', []
1706 return u'', []
1707
1707
1708 def dispatch_custom_completer(self, text):
1708 def dispatch_custom_completer(self, text):
1709 if not self.custom_completers:
1709 if not self.custom_completers:
1710 return
1710 return
1711
1711
1712 line = self.line_buffer
1712 line = self.line_buffer
1713 if not line.strip():
1713 if not line.strip():
1714 return None
1714 return None
1715
1715
1716 # Create a little structure to pass all the relevant information about
1716 # Create a little structure to pass all the relevant information about
1717 # the current completion to any custom completer.
1717 # the current completion to any custom completer.
1718 event = SimpleNamespace()
1718 event = SimpleNamespace()
1719 event.line = line
1719 event.line = line
1720 event.symbol = text
1720 event.symbol = text
1721 cmd = line.split(None,1)[0]
1721 cmd = line.split(None,1)[0]
1722 event.command = cmd
1722 event.command = cmd
1723 event.text_until_cursor = self.text_until_cursor
1723 event.text_until_cursor = self.text_until_cursor
1724
1724
1725 # for foo etc, try also to find completer for %foo
1725 # for foo etc, try also to find completer for %foo
1726 if not cmd.startswith(self.magic_escape):
1726 if not cmd.startswith(self.magic_escape):
1727 try_magic = self.custom_completers.s_matches(
1727 try_magic = self.custom_completers.s_matches(
1728 self.magic_escape + cmd)
1728 self.magic_escape + cmd)
1729 else:
1729 else:
1730 try_magic = []
1730 try_magic = []
1731
1731
1732 for c in itertools.chain(self.custom_completers.s_matches(cmd),
1732 for c in itertools.chain(self.custom_completers.s_matches(cmd),
1733 try_magic,
1733 try_magic,
1734 self.custom_completers.flat_matches(self.text_until_cursor)):
1734 self.custom_completers.flat_matches(self.text_until_cursor)):
1735 try:
1735 try:
1736 res = c(event)
1736 res = c(event)
1737 if res:
1737 if res:
1738 # first, try case sensitive match
1738 # first, try case sensitive match
1739 withcase = [r for r in res if r.startswith(text)]
1739 withcase = [r for r in res if r.startswith(text)]
1740 if withcase:
1740 if withcase:
1741 return withcase
1741 return withcase
1742 # if none, then case insensitive ones are ok too
1742 # if none, then case insensitive ones are ok too
1743 text_low = text.lower()
1743 text_low = text.lower()
1744 return [r for r in res if r.lower().startswith(text_low)]
1744 return [r for r in res if r.lower().startswith(text_low)]
1745 except TryNext:
1745 except TryNext:
1746 pass
1746 pass
1747 except KeyboardInterrupt:
1747 except KeyboardInterrupt:
1748 """
1748 """
1749 If custom completer take too long,
1749 If custom completer take too long,
1750 let keyboard interrupt abort and return nothing.
1750 let keyboard interrupt abort and return nothing.
1751 """
1751 """
1752 break
1752 break
1753
1753
1754 return None
1754 return None
1755
1755
1756 def completions(self, text: str, offset: int)->Iterator[Completion]:
1756 def completions(self, text: str, offset: int)->Iterator[Completion]:
1757 """
1757 """
1758 Returns an iterator over the possible completions
1758 Returns an iterator over the possible completions
1759
1759
1760 .. warning:: Unstable
1760 .. warning:: Unstable
1761
1761
1762 This function is unstable, API may change without warning.
1762 This function is unstable, API may change without warning.
1763 It will also raise unless use in proper context manager.
1763 It will also raise unless use in proper context manager.
1764
1764
1765 Parameters
1765 Parameters
1766 ----------
1766 ----------
1767
1767
1768 text:str
1768 text:str
1769 Full text of the current input, multi line string.
1769 Full text of the current input, multi line string.
1770 offset:int
1770 offset:int
1771 Integer representing the position of the cursor in ``text``. Offset
1771 Integer representing the position of the cursor in ``text``. Offset
1772 is 0-based indexed.
1772 is 0-based indexed.
1773
1773
1774 Yields
1774 Yields
1775 ------
1775 ------
1776 :any:`Completion` object
1776 :any:`Completion` object
1777
1777
1778
1778
1779 The cursor on a text can either be seen as being "in between"
1779 The cursor on a text can either be seen as being "in between"
1780 characters or "On" a character depending on the interface visible to
1780 characters or "On" a character depending on the interface visible to
1781 the user. For consistency the cursor being on "in between" characters X
1781 the user. For consistency the cursor being on "in between" characters X
1782 and Y is equivalent to the cursor being "on" character Y, that is to say
1782 and Y is equivalent to the cursor being "on" character Y, that is to say
1783 the character the cursor is on is considered as being after the cursor.
1783 the character the cursor is on is considered as being after the cursor.
1784
1784
1785 Combining characters may span more that one position in the
1785 Combining characters may span more that one position in the
1786 text.
1786 text.
1787
1787
1788
1788
1789 .. note::
1789 .. note::
1790
1790
1791 If ``IPCompleter.debug`` is :any:`True` will yield a ``--jedi/ipython--``
1791 If ``IPCompleter.debug`` is :any:`True` will yield a ``--jedi/ipython--``
1792 fake Completion token to distinguish completion returned by Jedi
1792 fake Completion token to distinguish completion returned by Jedi
1793 and usual IPython completion.
1793 and usual IPython completion.
1794
1794
1795 .. note::
1795 .. note::
1796
1796
1797 Completions are not completely deduplicated yet. If identical
1797 Completions are not completely deduplicated yet. If identical
1798 completions are coming from different sources this function does not
1798 completions are coming from different sources this function does not
1799 ensure that each completion object will only be present once.
1799 ensure that each completion object will only be present once.
1800 """
1800 """
1801 warnings.warn("_complete is a provisional API (as of IPython 6.0). "
1801 warnings.warn("_complete is a provisional API (as of IPython 6.0). "
1802 "It may change without warnings. "
1802 "It may change without warnings. "
1803 "Use in corresponding context manager.",
1803 "Use in corresponding context manager.",
1804 category=ProvisionalCompleterWarning, stacklevel=2)
1804 category=ProvisionalCompleterWarning, stacklevel=2)
1805
1805
1806 seen = set()
1806 seen = set()
1807 try:
1807 try:
1808 for c in self._completions(text, offset, _timeout=self.jedi_compute_type_timeout/1000):
1808 for c in self._completions(text, offset, _timeout=self.jedi_compute_type_timeout/1000):
1809 if c and (c in seen):
1809 if c and (c in seen):
1810 continue
1810 continue
1811 yield c
1811 yield c
1812 seen.add(c)
1812 seen.add(c)
1813 except KeyboardInterrupt:
1813 except KeyboardInterrupt:
1814 """if completions take too long and users send keyboard interrupt,
1814 """if completions take too long and users send keyboard interrupt,
1815 do not crash and return ASAP. """
1815 do not crash and return ASAP. """
1816 pass
1816 pass
1817
1817
1818 def _completions(self, full_text: str, offset: int, *, _timeout)->Iterator[Completion]:
1818 def _completions(self, full_text: str, offset: int, *, _timeout)->Iterator[Completion]:
1819 """
1819 """
1820 Core completion module.Same signature as :any:`completions`, with the
1820 Core completion module.Same signature as :any:`completions`, with the
1821 extra `timeout` parameter (in seconds).
1821 extra `timeout` parameter (in seconds).
1822
1822
1823
1823
1824 Computing jedi's completion ``.type`` can be quite expensive (it is a
1824 Computing jedi's completion ``.type`` can be quite expensive (it is a
1825 lazy property) and can require some warm-up, more warm up than just
1825 lazy property) and can require some warm-up, more warm up than just
1826 computing the ``name`` of a completion. The warm-up can be :
1826 computing the ``name`` of a completion. The warm-up can be :
1827
1827
1828 - Long warm-up the first time a module is encountered after
1828 - Long warm-up the first time a module is encountered after
1829 install/update: actually build parse/inference tree.
1829 install/update: actually build parse/inference tree.
1830
1830
1831 - first time the module is encountered in a session: load tree from
1831 - first time the module is encountered in a session: load tree from
1832 disk.
1832 disk.
1833
1833
1834 We don't want to block completions for tens of seconds so we give the
1834 We don't want to block completions for tens of seconds so we give the
1835 completer a "budget" of ``_timeout`` seconds per invocation to compute
1835 completer a "budget" of ``_timeout`` seconds per invocation to compute
1836 completions types, the completions that have not yet been computed will
1836 completions types, the completions that have not yet been computed will
1837 be marked as "unknown" an will have a chance to be computed next round
1837 be marked as "unknown" an will have a chance to be computed next round
1838 are things get cached.
1838 are things get cached.
1839
1839
1840 Keep in mind that Jedi is not the only thing treating the completion so
1840 Keep in mind that Jedi is not the only thing treating the completion so
1841 keep the timeout short-ish as if we take more than 0.3 second we still
1841 keep the timeout short-ish as if we take more than 0.3 second we still
1842 have lots of processing to do.
1842 have lots of processing to do.
1843
1843
1844 """
1844 """
1845 deadline = time.monotonic() + _timeout
1845 deadline = time.monotonic() + _timeout
1846
1846
1847
1847
1848 before = full_text[:offset]
1848 before = full_text[:offset]
1849 cursor_line, cursor_column = position_to_cursor(full_text, offset)
1849 cursor_line, cursor_column = position_to_cursor(full_text, offset)
1850
1850
1851 matched_text, matches, matches_origin, jedi_matches = self._complete(
1851 matched_text, matches, matches_origin, jedi_matches = self._complete(
1852 full_text=full_text, cursor_line=cursor_line, cursor_pos=cursor_column)
1852 full_text=full_text, cursor_line=cursor_line, cursor_pos=cursor_column)
1853
1853
1854 iter_jm = iter(jedi_matches)
1854 iter_jm = iter(jedi_matches)
1855 if _timeout:
1855 if _timeout:
1856 for jm in iter_jm:
1856 for jm in iter_jm:
1857 try:
1857 try:
1858 type_ = jm.type
1858 type_ = jm.type
1859 except Exception:
1859 except Exception:
1860 if self.debug:
1860 if self.debug:
1861 print("Error in Jedi getting type of ", jm)
1861 print("Error in Jedi getting type of ", jm)
1862 type_ = None
1862 type_ = None
1863 delta = len(jm.name_with_symbols) - len(jm.complete)
1863 delta = len(jm.name_with_symbols) - len(jm.complete)
1864 if type_ == 'function':
1864 if type_ == 'function':
1865 signature = _make_signature(jm)
1865 signature = _make_signature(jm)
1866 else:
1866 else:
1867 signature = ''
1867 signature = ''
1868 yield Completion(start=offset - delta,
1868 yield Completion(start=offset - delta,
1869 end=offset,
1869 end=offset,
1870 text=jm.name_with_symbols,
1870 text=jm.name_with_symbols,
1871 type=type_,
1871 type=type_,
1872 signature=signature,
1872 signature=signature,
1873 _origin='jedi')
1873 _origin='jedi')
1874
1874
1875 if time.monotonic() > deadline:
1875 if time.monotonic() > deadline:
1876 break
1876 break
1877
1877
1878 for jm in iter_jm:
1878 for jm in iter_jm:
1879 delta = len(jm.name_with_symbols) - len(jm.complete)
1879 delta = len(jm.name_with_symbols) - len(jm.complete)
1880 yield Completion(start=offset - delta,
1880 yield Completion(start=offset - delta,
1881 end=offset,
1881 end=offset,
1882 text=jm.name_with_symbols,
1882 text=jm.name_with_symbols,
1883 type='<unknown>', # don't compute type for speed
1883 type='<unknown>', # don't compute type for speed
1884 _origin='jedi',
1884 _origin='jedi',
1885 signature='')
1885 signature='')
1886
1886
1887
1887
1888 start_offset = before.rfind(matched_text)
1888 start_offset = before.rfind(matched_text)
1889
1889
1890 # TODO:
1890 # TODO:
1891 # Suppress this, right now just for debug.
1891 # Suppress this, right now just for debug.
1892 if jedi_matches and matches and self.debug:
1892 if jedi_matches and matches and self.debug:
1893 yield Completion(start=start_offset, end=offset, text='--jedi/ipython--',
1893 yield Completion(start=start_offset, end=offset, text='--jedi/ipython--',
1894 _origin='debug', type='none', signature='')
1894 _origin='debug', type='none', signature='')
1895
1895
1896 # I'm unsure if this is always true, so let's assert and see if it
1896 # I'm unsure if this is always true, so let's assert and see if it
1897 # crash
1897 # crash
1898 assert before.endswith(matched_text)
1898 assert before.endswith(matched_text)
1899 for m, t in zip(matches, matches_origin):
1899 for m, t in zip(matches, matches_origin):
1900 yield Completion(start=start_offset, end=offset, text=m, _origin=t, signature='', type='<unknown>')
1900 yield Completion(start=start_offset, end=offset, text=m, _origin=t, signature='', type='<unknown>')
1901
1901
1902
1902
1903 def complete(self, text=None, line_buffer=None, cursor_pos=None):
1903 def complete(self, text=None, line_buffer=None, cursor_pos=None):
1904 """Find completions for the given text and line context.
1904 """Find completions for the given text and line context.
1905
1905
1906 Note that both the text and the line_buffer are optional, but at least
1906 Note that both the text and the line_buffer are optional, but at least
1907 one of them must be given.
1907 one of them must be given.
1908
1908
1909 Parameters
1909 Parameters
1910 ----------
1910 ----------
1911 text : string, optional
1911 text : string, optional
1912 Text to perform the completion on. If not given, the line buffer
1912 Text to perform the completion on. If not given, the line buffer
1913 is split using the instance's CompletionSplitter object.
1913 is split using the instance's CompletionSplitter object.
1914
1914
1915 line_buffer : string, optional
1915 line_buffer : string, optional
1916 If not given, the completer attempts to obtain the current line
1916 If not given, the completer attempts to obtain the current line
1917 buffer via readline. This keyword allows clients which are
1917 buffer via readline. This keyword allows clients which are
1918 requesting for text completions in non-readline contexts to inform
1918 requesting for text completions in non-readline contexts to inform
1919 the completer of the entire text.
1919 the completer of the entire text.
1920
1920
1921 cursor_pos : int, optional
1921 cursor_pos : int, optional
1922 Index of the cursor in the full line buffer. Should be provided by
1922 Index of the cursor in the full line buffer. Should be provided by
1923 remote frontends where kernel has no access to frontend state.
1923 remote frontends where kernel has no access to frontend state.
1924
1924
1925 Returns
1925 Returns
1926 -------
1926 -------
1927 text : str
1927 text : str
1928 Text that was actually used in the completion.
1928 Text that was actually used in the completion.
1929
1929
1930 matches : list
1930 matches : list
1931 A list of completion matches.
1931 A list of completion matches.
1932
1932
1933
1933
1934 .. note::
1934 .. note::
1935
1935
1936 This API is likely to be deprecated and replaced by
1936 This API is likely to be deprecated and replaced by
1937 :any:`IPCompleter.completions` in the future.
1937 :any:`IPCompleter.completions` in the future.
1938
1938
1939
1939
1940 """
1940 """
1941 warnings.warn('`Completer.complete` is pending deprecation since '
1941 warnings.warn('`Completer.complete` is pending deprecation since '
1942 'IPython 6.0 and will be replaced by `Completer.completions`.',
1942 'IPython 6.0 and will be replaced by `Completer.completions`.',
1943 PendingDeprecationWarning)
1943 PendingDeprecationWarning)
1944 # potential todo, FOLD the 3rd throw away argument of _complete
1944 # potential todo, FOLD the 3rd throw away argument of _complete
1945 # into the first 2 one.
1945 # into the first 2 one.
1946 return self._complete(line_buffer=line_buffer, cursor_pos=cursor_pos, text=text, cursor_line=0)[:2]
1946 return self._complete(line_buffer=line_buffer, cursor_pos=cursor_pos, text=text, cursor_line=0)[:2]
1947
1947
1948 def _complete(self, *, cursor_line, cursor_pos, line_buffer=None, text=None,
1948 def _complete(self, *, cursor_line, cursor_pos, line_buffer=None, text=None,
1949 full_text=None) -> Tuple[str, List[str], List[str], Iterable[_FakeJediCompletion]]:
1949 full_text=None) -> Tuple[str, List[str], List[str], Iterable[_FakeJediCompletion]]:
1950 """
1950 """
1951
1951
1952 Like complete but can also returns raw jedi completions as well as the
1952 Like complete but can also returns raw jedi completions as well as the
1953 origin of the completion text. This could (and should) be made much
1953 origin of the completion text. This could (and should) be made much
1954 cleaner but that will be simpler once we drop the old (and stateful)
1954 cleaner but that will be simpler once we drop the old (and stateful)
1955 :any:`complete` API.
1955 :any:`complete` API.
1956
1956
1957
1957
1958 With current provisional API, cursor_pos act both (depending on the
1958 With current provisional API, cursor_pos act both (depending on the
1959 caller) as the offset in the ``text`` or ``line_buffer``, or as the
1959 caller) as the offset in the ``text`` or ``line_buffer``, or as the
1960 ``column`` when passing multiline strings this could/should be renamed
1960 ``column`` when passing multiline strings this could/should be renamed
1961 but would add extra noise.
1961 but would add extra noise.
1962 """
1962 """
1963
1963
1964 # if the cursor position isn't given, the only sane assumption we can
1964 # if the cursor position isn't given, the only sane assumption we can
1965 # make is that it's at the end of the line (the common case)
1965 # make is that it's at the end of the line (the common case)
1966 if cursor_pos is None:
1966 if cursor_pos is None:
1967 cursor_pos = len(line_buffer) if text is None else len(text)
1967 cursor_pos = len(line_buffer) if text is None else len(text)
1968
1968
1969 if self.use_main_ns:
1969 if self.use_main_ns:
1970 self.namespace = __main__.__dict__
1970 self.namespace = __main__.__dict__
1971
1971
1972 # if text is either None or an empty string, rely on the line buffer
1972 # if text is either None or an empty string, rely on the line buffer
1973 if (not line_buffer) and full_text:
1973 if (not line_buffer) and full_text:
1974 line_buffer = full_text.split('\n')[cursor_line]
1974 line_buffer = full_text.split('\n')[cursor_line]
1975 if not text:
1975 if not text:
1976 text = self.splitter.split_line(line_buffer, cursor_pos)
1976 text = self.splitter.split_line(line_buffer, cursor_pos)
1977
1977
1978 if self.backslash_combining_completions:
1978 if self.backslash_combining_completions:
1979 # allow deactivation of these on windows.
1979 # allow deactivation of these on windows.
1980 base_text = text if not line_buffer else line_buffer[:cursor_pos]
1980 base_text = text if not line_buffer else line_buffer[:cursor_pos]
1981 latex_text, latex_matches = self.latex_matches(base_text)
1981 latex_text, latex_matches = self.latex_matches(base_text)
1982 if latex_matches:
1982 if latex_matches:
1983 return latex_text, latex_matches, ['latex_matches']*len(latex_matches), ()
1983 return latex_text, latex_matches, ['latex_matches']*len(latex_matches), ()
1984 name_text = ''
1984 name_text = ''
1985 name_matches = []
1985 name_matches = []
1986 for meth in (self.unicode_name_matches, back_latex_name_matches, back_unicode_name_matches):
1986 for meth in (self.unicode_name_matches, back_latex_name_matches, back_unicode_name_matches):
1987 name_text, name_matches = meth(base_text)
1987 name_text, name_matches = meth(base_text)
1988 if name_text:
1988 if name_text:
1989 return name_text, name_matches[:MATCHES_LIMIT], \
1989 return name_text, name_matches[:MATCHES_LIMIT], \
1990 [meth.__qualname__]*min(len(name_matches), MATCHES_LIMIT), ()
1990 [meth.__qualname__]*min(len(name_matches), MATCHES_LIMIT), ()
1991
1991
1992
1992
1993 # If no line buffer is given, assume the input text is all there was
1993 # If no line buffer is given, assume the input text is all there was
1994 if line_buffer is None:
1994 if line_buffer is None:
1995 line_buffer = text
1995 line_buffer = text
1996
1996
1997 self.line_buffer = line_buffer
1997 self.line_buffer = line_buffer
1998 self.text_until_cursor = self.line_buffer[:cursor_pos]
1998 self.text_until_cursor = self.line_buffer[:cursor_pos]
1999
1999
2000 # Do magic arg matches
2000 # Do magic arg matches
2001 for matcher in self.magic_arg_matchers:
2001 for matcher in self.magic_arg_matchers:
2002 matches = list(matcher(line_buffer))[:MATCHES_LIMIT]
2002 matches = list(matcher(line_buffer))[:MATCHES_LIMIT]
2003 if matches:
2003 if matches:
2004 origins = [matcher.__qualname__] * len(matches)
2004 origins = [matcher.__qualname__] * len(matches)
2005 return text, matches, origins, ()
2005 return text, matches, origins, ()
2006
2006
2007 # Start with a clean slate of completions
2007 # Start with a clean slate of completions
2008 matches = []
2008 matches = []
2009 custom_res = self.dispatch_custom_completer(text)
2009 custom_res = self.dispatch_custom_completer(text)
2010 # FIXME: we should extend our api to return a dict with completions for
2010 # FIXME: we should extend our api to return a dict with completions for
2011 # different types of objects. The rlcomplete() method could then
2011 # different types of objects. The rlcomplete() method could then
2012 # simply collapse the dict into a list for readline, but we'd have
2012 # simply collapse the dict into a list for readline, but we'd have
2013 # richer completion semantics in other environments.
2013 # richer completion semantics in other environments.
2014 completions = ()
2014 completions = ()
2015 if self.use_jedi:
2015 if self.use_jedi:
2016 if not full_text:
2016 if not full_text:
2017 full_text = line_buffer
2017 full_text = line_buffer
2018 completions = self._jedi_matches(
2018 completions = self._jedi_matches(
2019 cursor_pos, cursor_line, full_text)
2019 cursor_pos, cursor_line, full_text)
2020 if custom_res is not None:
2020 if custom_res is not None:
2021 # did custom completers produce something?
2021 # did custom completers produce something?
2022 matches = [(m, 'custom') for m in custom_res]
2022 matches = [(m, 'custom') for m in custom_res]
2023 else:
2023 else:
2024 # Extend the list of completions with the results of each
2024 # Extend the list of completions with the results of each
2025 # matcher, so we return results to the user from all
2025 # matcher, so we return results to the user from all
2026 # namespaces.
2026 # namespaces.
2027 if self.merge_completions:
2027 if self.merge_completions:
2028 matches = []
2028 matches = []
2029 for matcher in self.matchers:
2029 for matcher in self.matchers:
2030 try:
2030 try:
2031 matches.extend([(m, matcher.__qualname__)
2031 matches.extend([(m, matcher.__qualname__)
2032 for m in matcher(text)])
2032 for m in matcher(text)])
2033 except:
2033 except:
2034 # Show the ugly traceback if the matcher causes an
2034 # Show the ugly traceback if the matcher causes an
2035 # exception, but do NOT crash the kernel!
2035 # exception, but do NOT crash the kernel!
2036 sys.excepthook(*sys.exc_info())
2036 sys.excepthook(*sys.exc_info())
2037 else:
2037 else:
2038 for matcher in self.matchers:
2038 for matcher in self.matchers:
2039 matches = [(m, matcher.__qualname__)
2039 matches = [(m, matcher.__qualname__)
2040 for m in matcher(text)]
2040 for m in matcher(text)]
2041 if matches:
2041 if matches:
2042 break
2042 break
2043 seen = set()
2043 seen = set()
2044 filtered_matches = set()
2044 filtered_matches = set()
2045 for m in matches:
2045 for m in matches:
2046 t, c = m
2046 t, c = m
2047 if t not in seen:
2047 if t not in seen:
2048 filtered_matches.add(m)
2048 filtered_matches.add(m)
2049 seen.add(t)
2049 seen.add(t)
2050
2050
2051 _filtered_matches = sorted(
2051 _filtered_matches = sorted(
2052 set(filtered_matches), key=lambda x: completions_sorting_key(x[0]))\
2052 set(filtered_matches), key=lambda x: completions_sorting_key(x[0]))\
2053 [:MATCHES_LIMIT]
2053 [:MATCHES_LIMIT]
2054
2054
2055 _matches = [m[0] for m in _filtered_matches]
2055 _matches = [m[0] for m in _filtered_matches]
2056 origins = [m[1] for m in _filtered_matches]
2056 origins = [m[1] for m in _filtered_matches]
2057
2057
2058 self.matches = _matches
2058 self.matches = _matches
2059
2059
2060 return text, _matches, origins, completions
2060 return text, _matches, origins, completions
@@ -1,354 +1,354 b''
1 # encoding: utf-8
1 # encoding: utf-8
2 """Implementations for various useful completers.
2 """Implementations for various useful completers.
3
3
4 These are all loaded by default by IPython.
4 These are all loaded by default by IPython.
5 """
5 """
6 #-----------------------------------------------------------------------------
6 #-----------------------------------------------------------------------------
7 # Copyright (C) 2010-2011 The IPython Development Team.
7 # Copyright (C) 2010-2011 The IPython Development Team.
8 #
8 #
9 # Distributed under the terms of the BSD License.
9 # Distributed under the terms of the BSD License.
10 #
10 #
11 # The full license is in the file COPYING.txt, distributed with this software.
11 # The full license is in the file COPYING.txt, distributed with this software.
12 #-----------------------------------------------------------------------------
12 #-----------------------------------------------------------------------------
13
13
14 #-----------------------------------------------------------------------------
14 #-----------------------------------------------------------------------------
15 # Imports
15 # Imports
16 #-----------------------------------------------------------------------------
16 #-----------------------------------------------------------------------------
17
17
18 # Stdlib imports
18 # Stdlib imports
19 import glob
19 import glob
20 import inspect
20 import inspect
21 import os
21 import os
22 import re
22 import re
23 import sys
23 import sys
24 from importlib import import_module
24 from importlib import import_module
25 from importlib.machinery import all_suffixes
25 from importlib.machinery import all_suffixes
26
26
27
27
28 # Third-party imports
28 # Third-party imports
29 from time import time
29 from time import time
30 from zipimport import zipimporter
30 from zipimport import zipimporter
31
31
32 # Our own imports
32 # Our own imports
33 from IPython.core.completer import expand_user, compress_user
33 from IPython.core.completer import expand_user, compress_user
34 from IPython.core.error import TryNext
34 from IPython.core.error import TryNext
35 from IPython.utils._process_common import arg_split
35 from IPython.utils._process_common import arg_split
36
36
37 # FIXME: this should be pulled in with the right call via the component system
37 # FIXME: this should be pulled in with the right call via the component system
38 from IPython import get_ipython
38 from IPython import get_ipython
39
39
40 from typing import List
40 from typing import List
41
41
42 #-----------------------------------------------------------------------------
42 #-----------------------------------------------------------------------------
43 # Globals and constants
43 # Globals and constants
44 #-----------------------------------------------------------------------------
44 #-----------------------------------------------------------------------------
45 _suffixes = all_suffixes()
45 _suffixes = all_suffixes()
46
46
47 # Time in seconds after which the rootmodules will be stored permanently in the
47 # Time in seconds after which the rootmodules will be stored permanently in the
48 # ipython ip.db database (kept in the user's .ipython dir).
48 # ipython ip.db database (kept in the user's .ipython dir).
49 TIMEOUT_STORAGE = 2
49 TIMEOUT_STORAGE = 2
50
50
51 # Time in seconds after which we give up
51 # Time in seconds after which we give up
52 TIMEOUT_GIVEUP = 20
52 TIMEOUT_GIVEUP = 20
53
53
54 # Regular expression for the python import statement
54 # Regular expression for the python import statement
55 import_re = re.compile(r'(?P<name>[a-zA-Z_][a-zA-Z0-9_]*?)'
55 import_re = re.compile(r'(?P<name>[a-zA-Z_][a-zA-Z0-9_]*?)'
56 r'(?P<package>[/\\]__init__)?'
56 r'(?P<package>[/\\]__init__)?'
57 r'(?P<suffix>%s)$' %
57 r'(?P<suffix>%s)$' %
58 r'|'.join(re.escape(s) for s in _suffixes))
58 r'|'.join(re.escape(s) for s in _suffixes))
59
59
60 # RE for the ipython %run command (python + ipython scripts)
60 # RE for the ipython %run command (python + ipython scripts)
61 magic_run_re = re.compile(r'.*(\.ipy|\.ipynb|\.py[w]?)$')
61 magic_run_re = re.compile(r'.*(\.ipy|\.ipynb|\.py[w]?)$')
62
62
63 #-----------------------------------------------------------------------------
63 #-----------------------------------------------------------------------------
64 # Local utilities
64 # Local utilities
65 #-----------------------------------------------------------------------------
65 #-----------------------------------------------------------------------------
66
66
67 def module_list(path):
67 def module_list(path):
68 """
68 """
69 Return the list containing the names of the modules available in the given
69 Return the list containing the names of the modules available in the given
70 folder.
70 folder.
71 """
71 """
72 # sys.path has the cwd as an empty string, but isdir/listdir need it as '.'
72 # sys.path has the cwd as an empty string, but isdir/listdir need it as '.'
73 if path == '':
73 if path == '':
74 path = '.'
74 path = '.'
75
75
76 # A few local constants to be used in loops below
76 # A few local constants to be used in loops below
77 pjoin = os.path.join
77 pjoin = os.path.join
78
78
79 if os.path.isdir(path):
79 if os.path.isdir(path):
80 # Build a list of all files in the directory and all files
80 # Build a list of all files in the directory and all files
81 # in its subdirectories. For performance reasons, do not
81 # in its subdirectories. For performance reasons, do not
82 # recurse more than one level into subdirectories.
82 # recurse more than one level into subdirectories.
83 files = []
83 files = []
84 for root, dirs, nondirs in os.walk(path, followlinks=True):
84 for root, dirs, nondirs in os.walk(path, followlinks=True):
85 subdir = root[len(path)+1:]
85 subdir = root[len(path)+1:]
86 if subdir:
86 if subdir:
87 files.extend(pjoin(subdir, f) for f in nondirs)
87 files.extend(pjoin(subdir, f) for f in nondirs)
88 dirs[:] = [] # Do not recurse into additional subdirectories.
88 dirs[:] = [] # Do not recurse into additional subdirectories.
89 else:
89 else:
90 files.extend(nondirs)
90 files.extend(nondirs)
91
91
92 else:
92 else:
93 try:
93 try:
94 files = list(zipimporter(path)._files.keys())
94 files = list(zipimporter(path)._files.keys())
95 except:
95 except:
96 files = []
96 files = []
97
97
98 # Build a list of modules which match the import_re regex.
98 # Build a list of modules which match the import_re regex.
99 modules = []
99 modules = []
100 for f in files:
100 for f in files:
101 m = import_re.match(f)
101 m = import_re.match(f)
102 if m:
102 if m:
103 modules.append(m.group('name'))
103 modules.append(m.group('name'))
104 return list(set(modules))
104 return list(set(modules))
105
105
106
106
107 def get_root_modules():
107 def get_root_modules():
108 """
108 """
109 Returns a list containing the names of all the modules available in the
109 Returns a list containing the names of all the modules available in the
110 folders of the pythonpath.
110 folders of the pythonpath.
111
111
112 ip.db['rootmodules_cache'] maps sys.path entries to list of modules.
112 ip.db['rootmodules_cache'] maps sys.path entries to list of modules.
113 """
113 """
114 ip = get_ipython()
114 ip = get_ipython()
115 if ip is None:
115 if ip is None:
116 # No global shell instance to store cached list of modules.
116 # No global shell instance to store cached list of modules.
117 # Don't try to scan for modules every time.
117 # Don't try to scan for modules every time.
118 return list(sys.builtin_module_names)
118 return list(sys.builtin_module_names)
119
119
120 rootmodules_cache = ip.db.get('rootmodules_cache', {})
120 rootmodules_cache = ip.db.get('rootmodules_cache', {})
121 rootmodules = list(sys.builtin_module_names)
121 rootmodules = list(sys.builtin_module_names)
122 start_time = time()
122 start_time = time()
123 store = False
123 store = False
124 for path in sys.path:
124 for path in sys.path:
125 try:
125 try:
126 modules = rootmodules_cache[path]
126 modules = rootmodules_cache[path]
127 except KeyError:
127 except KeyError:
128 modules = module_list(path)
128 modules = module_list(path)
129 try:
129 try:
130 modules.remove('__init__')
130 modules.remove('__init__')
131 except ValueError:
131 except ValueError:
132 pass
132 pass
133 if path not in ('', '.'): # cwd modules should not be cached
133 if path not in ('', '.'): # cwd modules should not be cached
134 rootmodules_cache[path] = modules
134 rootmodules_cache[path] = modules
135 if time() - start_time > TIMEOUT_STORAGE and not store:
135 if time() - start_time > TIMEOUT_STORAGE and not store:
136 store = True
136 store = True
137 print("\nCaching the list of root modules, please wait!")
137 print("\nCaching the list of root modules, please wait!")
138 print("(This will only be done once - type '%rehashx' to "
138 print("(This will only be done once - type '%rehashx' to "
139 "reset cache!)\n")
139 "reset cache!)\n")
140 sys.stdout.flush()
140 sys.stdout.flush()
141 if time() - start_time > TIMEOUT_GIVEUP:
141 if time() - start_time > TIMEOUT_GIVEUP:
142 print("This is taking too long, we give up.\n")
142 print("This is taking too long, we give up.\n")
143 return []
143 return []
144 rootmodules.extend(modules)
144 rootmodules.extend(modules)
145 if store:
145 if store:
146 ip.db['rootmodules_cache'] = rootmodules_cache
146 ip.db['rootmodules_cache'] = rootmodules_cache
147 rootmodules = list(set(rootmodules))
147 rootmodules = list(set(rootmodules))
148 return rootmodules
148 return rootmodules
149
149
150
150
151 def is_importable(module, attr, only_modules):
151 def is_importable(module, attr, only_modules):
152 if only_modules:
152 if only_modules:
153 return inspect.ismodule(getattr(module, attr))
153 return inspect.ismodule(getattr(module, attr))
154 else:
154 else:
155 return not(attr[:2] == '__' and attr[-2:] == '__')
155 return not(attr[:2] == '__' and attr[-2:] == '__')
156
156
157
157
158 def try_import(mod: str, only_modules=False) -> List[str]:
158 def try_import(mod: str, only_modules=False) -> List[str]:
159 """
159 """
160 Try to import given module and return list of potential completions.
160 Try to import given module and return list of potential completions.
161 """
161 """
162 mod = mod.rstrip('.')
162 mod = mod.rstrip('.')
163 try:
163 try:
164 m = import_module(mod)
164 m = import_module(mod)
165 except:
165 except:
166 return []
166 return []
167
167
168 m_is_init = hasattr(m, '__file__') and '__init__' in m.__file__
168 m_is_init = '__init__' in (getattr(m, '__file__', '') or '')
169
169
170 completions = []
170 completions = []
171 if (not hasattr(m, '__file__')) or (not only_modules) or m_is_init:
171 if (not hasattr(m, '__file__')) or (not only_modules) or m_is_init:
172 completions.extend( [attr for attr in dir(m) if
172 completions.extend( [attr for attr in dir(m) if
173 is_importable(m, attr, only_modules)])
173 is_importable(m, attr, only_modules)])
174
174
175 completions.extend(getattr(m, '__all__', []))
175 completions.extend(getattr(m, '__all__', []))
176 if m_is_init:
176 if m_is_init:
177 completions.extend(module_list(os.path.dirname(m.__file__)))
177 completions.extend(module_list(os.path.dirname(m.__file__)))
178 completions_set = {c for c in completions if isinstance(c, str)}
178 completions_set = {c for c in completions if isinstance(c, str)}
179 completions_set.discard('__init__')
179 completions_set.discard('__init__')
180 return list(completions_set)
180 return list(completions_set)
181
181
182
182
183 #-----------------------------------------------------------------------------
183 #-----------------------------------------------------------------------------
184 # Completion-related functions.
184 # Completion-related functions.
185 #-----------------------------------------------------------------------------
185 #-----------------------------------------------------------------------------
186
186
187 def quick_completer(cmd, completions):
187 def quick_completer(cmd, completions):
188 """ Easily create a trivial completer for a command.
188 """ Easily create a trivial completer for a command.
189
189
190 Takes either a list of completions, or all completions in string (that will
190 Takes either a list of completions, or all completions in string (that will
191 be split on whitespace).
191 be split on whitespace).
192
192
193 Example::
193 Example::
194
194
195 [d:\ipython]|1> import ipy_completers
195 [d:\ipython]|1> import ipy_completers
196 [d:\ipython]|2> ipy_completers.quick_completer('foo', ['bar','baz'])
196 [d:\ipython]|2> ipy_completers.quick_completer('foo', ['bar','baz'])
197 [d:\ipython]|3> foo b<TAB>
197 [d:\ipython]|3> foo b<TAB>
198 bar baz
198 bar baz
199 [d:\ipython]|3> foo ba
199 [d:\ipython]|3> foo ba
200 """
200 """
201
201
202 if isinstance(completions, str):
202 if isinstance(completions, str):
203 completions = completions.split()
203 completions = completions.split()
204
204
205 def do_complete(self, event):
205 def do_complete(self, event):
206 return completions
206 return completions
207
207
208 get_ipython().set_hook('complete_command',do_complete, str_key = cmd)
208 get_ipython().set_hook('complete_command',do_complete, str_key = cmd)
209
209
210 def module_completion(line):
210 def module_completion(line):
211 """
211 """
212 Returns a list containing the completion possibilities for an import line.
212 Returns a list containing the completion possibilities for an import line.
213
213
214 The line looks like this :
214 The line looks like this :
215 'import xml.d'
215 'import xml.d'
216 'from xml.dom import'
216 'from xml.dom import'
217 """
217 """
218
218
219 words = line.split(' ')
219 words = line.split(' ')
220 nwords = len(words)
220 nwords = len(words)
221
221
222 # from whatever <tab> -> 'import '
222 # from whatever <tab> -> 'import '
223 if nwords == 3 and words[0] == 'from':
223 if nwords == 3 and words[0] == 'from':
224 return ['import ']
224 return ['import ']
225
225
226 # 'from xy<tab>' or 'import xy<tab>'
226 # 'from xy<tab>' or 'import xy<tab>'
227 if nwords < 3 and (words[0] in {'%aimport', 'import', 'from'}) :
227 if nwords < 3 and (words[0] in {'%aimport', 'import', 'from'}) :
228 if nwords == 1:
228 if nwords == 1:
229 return get_root_modules()
229 return get_root_modules()
230 mod = words[1].split('.')
230 mod = words[1].split('.')
231 if len(mod) < 2:
231 if len(mod) < 2:
232 return get_root_modules()
232 return get_root_modules()
233 completion_list = try_import('.'.join(mod[:-1]), True)
233 completion_list = try_import('.'.join(mod[:-1]), True)
234 return ['.'.join(mod[:-1] + [el]) for el in completion_list]
234 return ['.'.join(mod[:-1] + [el]) for el in completion_list]
235
235
236 # 'from xyz import abc<tab>'
236 # 'from xyz import abc<tab>'
237 if nwords >= 3 and words[0] == 'from':
237 if nwords >= 3 and words[0] == 'from':
238 mod = words[1]
238 mod = words[1]
239 return try_import(mod)
239 return try_import(mod)
240
240
241 #-----------------------------------------------------------------------------
241 #-----------------------------------------------------------------------------
242 # Completers
242 # Completers
243 #-----------------------------------------------------------------------------
243 #-----------------------------------------------------------------------------
244 # These all have the func(self, event) signature to be used as custom
244 # These all have the func(self, event) signature to be used as custom
245 # completers
245 # completers
246
246
247 def module_completer(self,event):
247 def module_completer(self,event):
248 """Give completions after user has typed 'import ...' or 'from ...'"""
248 """Give completions after user has typed 'import ...' or 'from ...'"""
249
249
250 # This works in all versions of python. While 2.5 has
250 # This works in all versions of python. While 2.5 has
251 # pkgutil.walk_packages(), that particular routine is fairly dangerous,
251 # pkgutil.walk_packages(), that particular routine is fairly dangerous,
252 # since it imports *EVERYTHING* on sys.path. That is: a) very slow b) full
252 # since it imports *EVERYTHING* on sys.path. That is: a) very slow b) full
253 # of possibly problematic side effects.
253 # of possibly problematic side effects.
254 # This search the folders in the sys.path for available modules.
254 # This search the folders in the sys.path for available modules.
255
255
256 return module_completion(event.line)
256 return module_completion(event.line)
257
257
258 # FIXME: there's a lot of logic common to the run, cd and builtin file
258 # FIXME: there's a lot of logic common to the run, cd and builtin file
259 # completers, that is currently reimplemented in each.
259 # completers, that is currently reimplemented in each.
260
260
261 def magic_run_completer(self, event):
261 def magic_run_completer(self, event):
262 """Complete files that end in .py or .ipy or .ipynb for the %run command.
262 """Complete files that end in .py or .ipy or .ipynb for the %run command.
263 """
263 """
264 comps = arg_split(event.line, strict=False)
264 comps = arg_split(event.line, strict=False)
265 # relpath should be the current token that we need to complete.
265 # relpath should be the current token that we need to complete.
266 if (len(comps) > 1) and (not event.line.endswith(' ')):
266 if (len(comps) > 1) and (not event.line.endswith(' ')):
267 relpath = comps[-1].strip("'\"")
267 relpath = comps[-1].strip("'\"")
268 else:
268 else:
269 relpath = ''
269 relpath = ''
270
270
271 #print("\nev=", event) # dbg
271 #print("\nev=", event) # dbg
272 #print("rp=", relpath) # dbg
272 #print("rp=", relpath) # dbg
273 #print('comps=', comps) # dbg
273 #print('comps=', comps) # dbg
274
274
275 lglob = glob.glob
275 lglob = glob.glob
276 isdir = os.path.isdir
276 isdir = os.path.isdir
277 relpath, tilde_expand, tilde_val = expand_user(relpath)
277 relpath, tilde_expand, tilde_val = expand_user(relpath)
278
278
279 # Find if the user has already typed the first filename, after which we
279 # Find if the user has already typed the first filename, after which we
280 # should complete on all files, since after the first one other files may
280 # should complete on all files, since after the first one other files may
281 # be arguments to the input script.
281 # be arguments to the input script.
282
282
283 if any(magic_run_re.match(c) for c in comps):
283 if any(magic_run_re.match(c) for c in comps):
284 matches = [f.replace('\\','/') + ('/' if isdir(f) else '')
284 matches = [f.replace('\\','/') + ('/' if isdir(f) else '')
285 for f in lglob(relpath+'*')]
285 for f in lglob(relpath+'*')]
286 else:
286 else:
287 dirs = [f.replace('\\','/') + "/" for f in lglob(relpath+'*') if isdir(f)]
287 dirs = [f.replace('\\','/') + "/" for f in lglob(relpath+'*') if isdir(f)]
288 pys = [f.replace('\\','/')
288 pys = [f.replace('\\','/')
289 for f in lglob(relpath+'*.py') + lglob(relpath+'*.ipy') +
289 for f in lglob(relpath+'*.py') + lglob(relpath+'*.ipy') +
290 lglob(relpath+'*.ipynb') + lglob(relpath + '*.pyw')]
290 lglob(relpath+'*.ipynb') + lglob(relpath + '*.pyw')]
291
291
292 matches = dirs + pys
292 matches = dirs + pys
293
293
294 #print('run comp:', dirs+pys) # dbg
294 #print('run comp:', dirs+pys) # dbg
295 return [compress_user(p, tilde_expand, tilde_val) for p in matches]
295 return [compress_user(p, tilde_expand, tilde_val) for p in matches]
296
296
297
297
298 def cd_completer(self, event):
298 def cd_completer(self, event):
299 """Completer function for cd, which only returns directories."""
299 """Completer function for cd, which only returns directories."""
300 ip = get_ipython()
300 ip = get_ipython()
301 relpath = event.symbol
301 relpath = event.symbol
302
302
303 #print(event) # dbg
303 #print(event) # dbg
304 if event.line.endswith('-b') or ' -b ' in event.line:
304 if event.line.endswith('-b') or ' -b ' in event.line:
305 # return only bookmark completions
305 # return only bookmark completions
306 bkms = self.db.get('bookmarks', None)
306 bkms = self.db.get('bookmarks', None)
307 if bkms:
307 if bkms:
308 return bkms.keys()
308 return bkms.keys()
309 else:
309 else:
310 return []
310 return []
311
311
312 if event.symbol == '-':
312 if event.symbol == '-':
313 width_dh = str(len(str(len(ip.user_ns['_dh']) + 1)))
313 width_dh = str(len(str(len(ip.user_ns['_dh']) + 1)))
314 # jump in directory history by number
314 # jump in directory history by number
315 fmt = '-%0' + width_dh +'d [%s]'
315 fmt = '-%0' + width_dh +'d [%s]'
316 ents = [ fmt % (i,s) for i,s in enumerate(ip.user_ns['_dh'])]
316 ents = [ fmt % (i,s) for i,s in enumerate(ip.user_ns['_dh'])]
317 if len(ents) > 1:
317 if len(ents) > 1:
318 return ents
318 return ents
319 return []
319 return []
320
320
321 if event.symbol.startswith('--'):
321 if event.symbol.startswith('--'):
322 return ["--" + os.path.basename(d) for d in ip.user_ns['_dh']]
322 return ["--" + os.path.basename(d) for d in ip.user_ns['_dh']]
323
323
324 # Expand ~ in path and normalize directory separators.
324 # Expand ~ in path and normalize directory separators.
325 relpath, tilde_expand, tilde_val = expand_user(relpath)
325 relpath, tilde_expand, tilde_val = expand_user(relpath)
326 relpath = relpath.replace('\\','/')
326 relpath = relpath.replace('\\','/')
327
327
328 found = []
328 found = []
329 for d in [f.replace('\\','/') + '/' for f in glob.glob(relpath+'*')
329 for d in [f.replace('\\','/') + '/' for f in glob.glob(relpath+'*')
330 if os.path.isdir(f)]:
330 if os.path.isdir(f)]:
331 if ' ' in d:
331 if ' ' in d:
332 # we don't want to deal with any of that, complex code
332 # we don't want to deal with any of that, complex code
333 # for this is elsewhere
333 # for this is elsewhere
334 raise TryNext
334 raise TryNext
335
335
336 found.append(d)
336 found.append(d)
337
337
338 if not found:
338 if not found:
339 if os.path.isdir(relpath):
339 if os.path.isdir(relpath):
340 return [compress_user(relpath, tilde_expand, tilde_val)]
340 return [compress_user(relpath, tilde_expand, tilde_val)]
341
341
342 # if no completions so far, try bookmarks
342 # if no completions so far, try bookmarks
343 bks = self.db.get('bookmarks',{})
343 bks = self.db.get('bookmarks',{})
344 bkmatches = [s for s in bks if s.startswith(event.symbol)]
344 bkmatches = [s for s in bks if s.startswith(event.symbol)]
345 if bkmatches:
345 if bkmatches:
346 return bkmatches
346 return bkmatches
347
347
348 raise TryNext
348 raise TryNext
349
349
350 return [compress_user(p, tilde_expand, tilde_val) for p in found]
350 return [compress_user(p, tilde_expand, tilde_val) for p in found]
351
351
352 def reset_completer(self, event):
352 def reset_completer(self, event):
353 "A completer for %reset magic"
353 "A completer for %reset magic"
354 return '-f -s in out array dhist'.split()
354 return '-f -s in out array dhist'.split()
@@ -1,645 +1,645 b''
1 # -*- coding: utf-8 -*-
1 # -*- coding: utf-8 -*-
2 """
2 """
3 Pdb debugger class.
3 Pdb debugger class.
4
4
5 Modified from the standard pdb.Pdb class to avoid including readline, so that
5 Modified from the standard pdb.Pdb class to avoid including readline, so that
6 the command line completion of other programs which include this isn't
6 the command line completion of other programs which include this isn't
7 damaged.
7 damaged.
8
8
9 In the future, this class will be expanded with improvements over the standard
9 In the future, this class will be expanded with improvements over the standard
10 pdb.
10 pdb.
11
11
12 The code in this file is mainly lifted out of cmd.py in Python 2.2, with minor
12 The code in this file is mainly lifted out of cmd.py in Python 2.2, with minor
13 changes. Licensing should therefore be under the standard Python terms. For
13 changes. Licensing should therefore be under the standard Python terms. For
14 details on the PSF (Python Software Foundation) standard license, see:
14 details on the PSF (Python Software Foundation) standard license, see:
15
15
16 https://docs.python.org/2/license.html
16 https://docs.python.org/2/license.html
17 """
17 """
18
18
19 #*****************************************************************************
19 #*****************************************************************************
20 #
20 #
21 # This file is licensed under the PSF license.
21 # This file is licensed under the PSF license.
22 #
22 #
23 # Copyright (C) 2001 Python Software Foundation, www.python.org
23 # Copyright (C) 2001 Python Software Foundation, www.python.org
24 # Copyright (C) 2005-2006 Fernando Perez. <fperez@colorado.edu>
24 # Copyright (C) 2005-2006 Fernando Perez. <fperez@colorado.edu>
25 #
25 #
26 #
26 #
27 #*****************************************************************************
27 #*****************************************************************************
28
28
29 import bdb
29 import bdb
30 import functools
30 import functools
31 import inspect
31 import inspect
32 import linecache
32 import linecache
33 import sys
33 import sys
34 import warnings
34 import warnings
35 import re
35 import re
36
36
37 from IPython import get_ipython
37 from IPython import get_ipython
38 from IPython.utils import PyColorize
38 from IPython.utils import PyColorize
39 from IPython.utils import coloransi, py3compat
39 from IPython.utils import coloransi, py3compat
40 from IPython.core.excolors import exception_colors
40 from IPython.core.excolors import exception_colors
41 from IPython.testing.skipdoctest import skip_doctest
41 from IPython.testing.skipdoctest import skip_doctest
42
42
43
43
44 prompt = 'ipdb> '
44 prompt = 'ipdb> '
45
45
46 #We have to check this directly from sys.argv, config struct not yet available
46 #We have to check this directly from sys.argv, config struct not yet available
47 from pdb import Pdb as OldPdb
47 from pdb import Pdb as OldPdb
48
48
49 # Allow the set_trace code to operate outside of an ipython instance, even if
49 # Allow the set_trace code to operate outside of an ipython instance, even if
50 # it does so with some limitations. The rest of this support is implemented in
50 # it does so with some limitations. The rest of this support is implemented in
51 # the Tracer constructor.
51 # the Tracer constructor.
52
52
53 def make_arrow(pad):
53 def make_arrow(pad):
54 """generate the leading arrow in front of traceback or debugger"""
54 """generate the leading arrow in front of traceback or debugger"""
55 if pad >= 2:
55 if pad >= 2:
56 return '-'*(pad-2) + '> '
56 return '-'*(pad-2) + '> '
57 elif pad == 1:
57 elif pad == 1:
58 return '>'
58 return '>'
59 return ''
59 return ''
60
60
61
61
62 def BdbQuit_excepthook(et, ev, tb, excepthook=None):
62 def BdbQuit_excepthook(et, ev, tb, excepthook=None):
63 """Exception hook which handles `BdbQuit` exceptions.
63 """Exception hook which handles `BdbQuit` exceptions.
64
64
65 All other exceptions are processed using the `excepthook`
65 All other exceptions are processed using the `excepthook`
66 parameter.
66 parameter.
67 """
67 """
68 warnings.warn("`BdbQuit_excepthook` is deprecated since version 5.1",
68 warnings.warn("`BdbQuit_excepthook` is deprecated since version 5.1",
69 DeprecationWarning, stacklevel=2)
69 DeprecationWarning, stacklevel=2)
70 if et==bdb.BdbQuit:
70 if et==bdb.BdbQuit:
71 print('Exiting Debugger.')
71 print('Exiting Debugger.')
72 elif excepthook is not None:
72 elif excepthook is not None:
73 excepthook(et, ev, tb)
73 excepthook(et, ev, tb)
74 else:
74 else:
75 # Backwards compatibility. Raise deprecation warning?
75 # Backwards compatibility. Raise deprecation warning?
76 BdbQuit_excepthook.excepthook_ori(et,ev,tb)
76 BdbQuit_excepthook.excepthook_ori(et,ev,tb)
77
77
78
78
79 def BdbQuit_IPython_excepthook(self,et,ev,tb,tb_offset=None):
79 def BdbQuit_IPython_excepthook(self,et,ev,tb,tb_offset=None):
80 warnings.warn(
80 warnings.warn(
81 "`BdbQuit_IPython_excepthook` is deprecated since version 5.1",
81 "`BdbQuit_IPython_excepthook` is deprecated since version 5.1",
82 DeprecationWarning, stacklevel=2)
82 DeprecationWarning, stacklevel=2)
83 print('Exiting Debugger.')
83 print('Exiting Debugger.')
84
84
85
85
86 class Tracer(object):
86 class Tracer(object):
87 """
87 """
88 DEPRECATED
88 DEPRECATED
89
89
90 Class for local debugging, similar to pdb.set_trace.
90 Class for local debugging, similar to pdb.set_trace.
91
91
92 Instances of this class, when called, behave like pdb.set_trace, but
92 Instances of this class, when called, behave like pdb.set_trace, but
93 providing IPython's enhanced capabilities.
93 providing IPython's enhanced capabilities.
94
94
95 This is implemented as a class which must be initialized in your own code
95 This is implemented as a class which must be initialized in your own code
96 and not as a standalone function because we need to detect at runtime
96 and not as a standalone function because we need to detect at runtime
97 whether IPython is already active or not. That detection is done in the
97 whether IPython is already active or not. That detection is done in the
98 constructor, ensuring that this code plays nicely with a running IPython,
98 constructor, ensuring that this code plays nicely with a running IPython,
99 while functioning acceptably (though with limitations) if outside of it.
99 while functioning acceptably (though with limitations) if outside of it.
100 """
100 """
101
101
102 @skip_doctest
102 @skip_doctest
103 def __init__(self, colors=None):
103 def __init__(self, colors=None):
104 """
104 """
105 DEPRECATED
105 DEPRECATED
106
106
107 Create a local debugger instance.
107 Create a local debugger instance.
108
108
109 Parameters
109 Parameters
110 ----------
110 ----------
111
111
112 colors : str, optional
112 colors : str, optional
113 The name of the color scheme to use, it must be one of IPython's
113 The name of the color scheme to use, it must be one of IPython's
114 valid color schemes. If not given, the function will default to
114 valid color schemes. If not given, the function will default to
115 the current IPython scheme when running inside IPython, and to
115 the current IPython scheme when running inside IPython, and to
116 'NoColor' otherwise.
116 'NoColor' otherwise.
117
117
118 Examples
118 Examples
119 --------
119 --------
120 ::
120 ::
121
121
122 from IPython.core.debugger import Tracer; debug_here = Tracer()
122 from IPython.core.debugger import Tracer; debug_here = Tracer()
123
123
124 Later in your code::
124 Later in your code::
125
125
126 debug_here() # -> will open up the debugger at that point.
126 debug_here() # -> will open up the debugger at that point.
127
127
128 Once the debugger activates, you can use all of its regular commands to
128 Once the debugger activates, you can use all of its regular commands to
129 step through code, set breakpoints, etc. See the pdb documentation
129 step through code, set breakpoints, etc. See the pdb documentation
130 from the Python standard library for usage details.
130 from the Python standard library for usage details.
131 """
131 """
132 warnings.warn("`Tracer` is deprecated since version 5.1, directly use "
132 warnings.warn("`Tracer` is deprecated since version 5.1, directly use "
133 "`IPython.core.debugger.Pdb.set_trace()`",
133 "`IPython.core.debugger.Pdb.set_trace()`",
134 DeprecationWarning, stacklevel=2)
134 DeprecationWarning, stacklevel=2)
135
135
136 ip = get_ipython()
136 ip = get_ipython()
137 if ip is None:
137 if ip is None:
138 # Outside of ipython, we set our own exception hook manually
138 # Outside of ipython, we set our own exception hook manually
139 sys.excepthook = functools.partial(BdbQuit_excepthook,
139 sys.excepthook = functools.partial(BdbQuit_excepthook,
140 excepthook=sys.excepthook)
140 excepthook=sys.excepthook)
141 def_colors = 'NoColor'
141 def_colors = 'NoColor'
142 else:
142 else:
143 # In ipython, we use its custom exception handler mechanism
143 # In ipython, we use its custom exception handler mechanism
144 def_colors = ip.colors
144 def_colors = ip.colors
145 ip.set_custom_exc((bdb.BdbQuit,), BdbQuit_IPython_excepthook)
145 ip.set_custom_exc((bdb.BdbQuit,), BdbQuit_IPython_excepthook)
146
146
147 if colors is None:
147 if colors is None:
148 colors = def_colors
148 colors = def_colors
149
149
150 # The stdlib debugger internally uses a modified repr from the `repr`
150 # The stdlib debugger internally uses a modified repr from the `repr`
151 # module, that limits the length of printed strings to a hardcoded
151 # module, that limits the length of printed strings to a hardcoded
152 # limit of 30 characters. That much trimming is too aggressive, let's
152 # limit of 30 characters. That much trimming is too aggressive, let's
153 # at least raise that limit to 80 chars, which should be enough for
153 # at least raise that limit to 80 chars, which should be enough for
154 # most interactive uses.
154 # most interactive uses.
155 try:
155 try:
156 try:
156 try:
157 from reprlib import aRepr # Py 3
157 from reprlib import aRepr # Py 3
158 except ImportError:
158 except ImportError:
159 from repr import aRepr # Py 2
159 from repr import aRepr # Py 2
160 aRepr.maxstring = 80
160 aRepr.maxstring = 80
161 except:
161 except:
162 # This is only a user-facing convenience, so any error we encounter
162 # This is only a user-facing convenience, so any error we encounter
163 # here can be warned about but can be otherwise ignored. These
163 # here can be warned about but can be otherwise ignored. These
164 # printouts will tell us about problems if this API changes
164 # printouts will tell us about problems if this API changes
165 import traceback
165 import traceback
166 traceback.print_exc()
166 traceback.print_exc()
167
167
168 self.debugger = Pdb(colors)
168 self.debugger = Pdb(colors)
169
169
170 def __call__(self):
170 def __call__(self):
171 """Starts an interactive debugger at the point where called.
171 """Starts an interactive debugger at the point where called.
172
172
173 This is similar to the pdb.set_trace() function from the std lib, but
173 This is similar to the pdb.set_trace() function from the std lib, but
174 using IPython's enhanced debugger."""
174 using IPython's enhanced debugger."""
175
175
176 self.debugger.set_trace(sys._getframe().f_back)
176 self.debugger.set_trace(sys._getframe().f_back)
177
177
178
178
179 RGX_EXTRA_INDENT = re.compile('(?<=\n)\s+')
179 RGX_EXTRA_INDENT = re.compile(r'(?<=\n)\s+')
180
180
181
181
182 def strip_indentation(multiline_string):
182 def strip_indentation(multiline_string):
183 return RGX_EXTRA_INDENT.sub('', multiline_string)
183 return RGX_EXTRA_INDENT.sub('', multiline_string)
184
184
185
185
186 def decorate_fn_with_doc(new_fn, old_fn, additional_text=""):
186 def decorate_fn_with_doc(new_fn, old_fn, additional_text=""):
187 """Make new_fn have old_fn's doc string. This is particularly useful
187 """Make new_fn have old_fn's doc string. This is particularly useful
188 for the ``do_...`` commands that hook into the help system.
188 for the ``do_...`` commands that hook into the help system.
189 Adapted from from a comp.lang.python posting
189 Adapted from from a comp.lang.python posting
190 by Duncan Booth."""
190 by Duncan Booth."""
191 def wrapper(*args, **kw):
191 def wrapper(*args, **kw):
192 return new_fn(*args, **kw)
192 return new_fn(*args, **kw)
193 if old_fn.__doc__:
193 if old_fn.__doc__:
194 wrapper.__doc__ = strip_indentation(old_fn.__doc__) + additional_text
194 wrapper.__doc__ = strip_indentation(old_fn.__doc__) + additional_text
195 return wrapper
195 return wrapper
196
196
197
197
198 def _file_lines(fname):
198 def _file_lines(fname):
199 """Return the contents of a named file as a list of lines.
199 """Return the contents of a named file as a list of lines.
200
200
201 This function never raises an IOError exception: if the file can't be
201 This function never raises an IOError exception: if the file can't be
202 read, it simply returns an empty list."""
202 read, it simply returns an empty list."""
203
203
204 try:
204 try:
205 outfile = open(fname)
205 outfile = open(fname)
206 except IOError:
206 except IOError:
207 return []
207 return []
208 else:
208 else:
209 out = outfile.readlines()
209 out = outfile.readlines()
210 outfile.close()
210 outfile.close()
211 return out
211 return out
212
212
213
213
214 class Pdb(OldPdb):
214 class Pdb(OldPdb):
215 """Modified Pdb class, does not load readline.
215 """Modified Pdb class, does not load readline.
216
216
217 for a standalone version that uses prompt_toolkit, see
217 for a standalone version that uses prompt_toolkit, see
218 `IPython.terminal.debugger.TerminalPdb` and
218 `IPython.terminal.debugger.TerminalPdb` and
219 `IPython.terminal.debugger.set_trace()`
219 `IPython.terminal.debugger.set_trace()`
220 """
220 """
221
221
222 def __init__(self, color_scheme=None, completekey=None,
222 def __init__(self, color_scheme=None, completekey=None,
223 stdin=None, stdout=None, context=5):
223 stdin=None, stdout=None, context=5):
224
224
225 # Parent constructor:
225 # Parent constructor:
226 try:
226 try:
227 self.context = int(context)
227 self.context = int(context)
228 if self.context <= 0:
228 if self.context <= 0:
229 raise ValueError("Context must be a positive integer")
229 raise ValueError("Context must be a positive integer")
230 except (TypeError, ValueError):
230 except (TypeError, ValueError):
231 raise ValueError("Context must be a positive integer")
231 raise ValueError("Context must be a positive integer")
232
232
233 OldPdb.__init__(self, completekey, stdin, stdout)
233 OldPdb.__init__(self, completekey, stdin, stdout)
234
234
235 # IPython changes...
235 # IPython changes...
236 self.shell = get_ipython()
236 self.shell = get_ipython()
237
237
238 if self.shell is None:
238 if self.shell is None:
239 save_main = sys.modules['__main__']
239 save_main = sys.modules['__main__']
240 # No IPython instance running, we must create one
240 # No IPython instance running, we must create one
241 from IPython.terminal.interactiveshell import \
241 from IPython.terminal.interactiveshell import \
242 TerminalInteractiveShell
242 TerminalInteractiveShell
243 self.shell = TerminalInteractiveShell.instance()
243 self.shell = TerminalInteractiveShell.instance()
244 # needed by any code which calls __import__("__main__") after
244 # needed by any code which calls __import__("__main__") after
245 # the debugger was entered. See also #9941.
245 # the debugger was entered. See also #9941.
246 sys.modules['__main__'] = save_main
246 sys.modules['__main__'] = save_main
247
247
248 if color_scheme is not None:
248 if color_scheme is not None:
249 warnings.warn(
249 warnings.warn(
250 "The `color_scheme` argument is deprecated since version 5.1",
250 "The `color_scheme` argument is deprecated since version 5.1",
251 DeprecationWarning, stacklevel=2)
251 DeprecationWarning, stacklevel=2)
252 else:
252 else:
253 color_scheme = self.shell.colors
253 color_scheme = self.shell.colors
254
254
255 self.aliases = {}
255 self.aliases = {}
256
256
257 # Create color table: we copy the default one from the traceback
257 # Create color table: we copy the default one from the traceback
258 # module and add a few attributes needed for debugging
258 # module and add a few attributes needed for debugging
259 self.color_scheme_table = exception_colors()
259 self.color_scheme_table = exception_colors()
260
260
261 # shorthands
261 # shorthands
262 C = coloransi.TermColors
262 C = coloransi.TermColors
263 cst = self.color_scheme_table
263 cst = self.color_scheme_table
264
264
265 cst['NoColor'].colors.prompt = C.NoColor
265 cst['NoColor'].colors.prompt = C.NoColor
266 cst['NoColor'].colors.breakpoint_enabled = C.NoColor
266 cst['NoColor'].colors.breakpoint_enabled = C.NoColor
267 cst['NoColor'].colors.breakpoint_disabled = C.NoColor
267 cst['NoColor'].colors.breakpoint_disabled = C.NoColor
268
268
269 cst['Linux'].colors.prompt = C.Green
269 cst['Linux'].colors.prompt = C.Green
270 cst['Linux'].colors.breakpoint_enabled = C.LightRed
270 cst['Linux'].colors.breakpoint_enabled = C.LightRed
271 cst['Linux'].colors.breakpoint_disabled = C.Red
271 cst['Linux'].colors.breakpoint_disabled = C.Red
272
272
273 cst['LightBG'].colors.prompt = C.Blue
273 cst['LightBG'].colors.prompt = C.Blue
274 cst['LightBG'].colors.breakpoint_enabled = C.LightRed
274 cst['LightBG'].colors.breakpoint_enabled = C.LightRed
275 cst['LightBG'].colors.breakpoint_disabled = C.Red
275 cst['LightBG'].colors.breakpoint_disabled = C.Red
276
276
277 cst['Neutral'].colors.prompt = C.Blue
277 cst['Neutral'].colors.prompt = C.Blue
278 cst['Neutral'].colors.breakpoint_enabled = C.LightRed
278 cst['Neutral'].colors.breakpoint_enabled = C.LightRed
279 cst['Neutral'].colors.breakpoint_disabled = C.Red
279 cst['Neutral'].colors.breakpoint_disabled = C.Red
280
280
281
281
282 # Add a python parser so we can syntax highlight source while
282 # Add a python parser so we can syntax highlight source while
283 # debugging.
283 # debugging.
284 self.parser = PyColorize.Parser(style=color_scheme)
284 self.parser = PyColorize.Parser(style=color_scheme)
285 self.set_colors(color_scheme)
285 self.set_colors(color_scheme)
286
286
287 # Set the prompt - the default prompt is '(Pdb)'
287 # Set the prompt - the default prompt is '(Pdb)'
288 self.prompt = prompt
288 self.prompt = prompt
289
289
290 def set_colors(self, scheme):
290 def set_colors(self, scheme):
291 """Shorthand access to the color table scheme selector method."""
291 """Shorthand access to the color table scheme selector method."""
292 self.color_scheme_table.set_active_scheme(scheme)
292 self.color_scheme_table.set_active_scheme(scheme)
293 self.parser.style = scheme
293 self.parser.style = scheme
294
294
295 def interaction(self, frame, traceback):
295 def interaction(self, frame, traceback):
296 try:
296 try:
297 OldPdb.interaction(self, frame, traceback)
297 OldPdb.interaction(self, frame, traceback)
298 except KeyboardInterrupt:
298 except KeyboardInterrupt:
299 sys.stdout.write('\n' + self.shell.get_exception_only())
299 sys.stdout.write('\n' + self.shell.get_exception_only())
300
300
301 def new_do_up(self, arg):
301 def new_do_up(self, arg):
302 OldPdb.do_up(self, arg)
302 OldPdb.do_up(self, arg)
303 do_u = do_up = decorate_fn_with_doc(new_do_up, OldPdb.do_up)
303 do_u = do_up = decorate_fn_with_doc(new_do_up, OldPdb.do_up)
304
304
305 def new_do_down(self, arg):
305 def new_do_down(self, arg):
306 OldPdb.do_down(self, arg)
306 OldPdb.do_down(self, arg)
307
307
308 do_d = do_down = decorate_fn_with_doc(new_do_down, OldPdb.do_down)
308 do_d = do_down = decorate_fn_with_doc(new_do_down, OldPdb.do_down)
309
309
310 def new_do_frame(self, arg):
310 def new_do_frame(self, arg):
311 OldPdb.do_frame(self, arg)
311 OldPdb.do_frame(self, arg)
312
312
313 def new_do_quit(self, arg):
313 def new_do_quit(self, arg):
314
314
315 if hasattr(self, 'old_all_completions'):
315 if hasattr(self, 'old_all_completions'):
316 self.shell.Completer.all_completions=self.old_all_completions
316 self.shell.Completer.all_completions=self.old_all_completions
317
317
318 return OldPdb.do_quit(self, arg)
318 return OldPdb.do_quit(self, arg)
319
319
320 do_q = do_quit = decorate_fn_with_doc(new_do_quit, OldPdb.do_quit)
320 do_q = do_quit = decorate_fn_with_doc(new_do_quit, OldPdb.do_quit)
321
321
322 def new_do_restart(self, arg):
322 def new_do_restart(self, arg):
323 """Restart command. In the context of ipython this is exactly the same
323 """Restart command. In the context of ipython this is exactly the same
324 thing as 'quit'."""
324 thing as 'quit'."""
325 self.msg("Restart doesn't make sense here. Using 'quit' instead.")
325 self.msg("Restart doesn't make sense here. Using 'quit' instead.")
326 return self.do_quit(arg)
326 return self.do_quit(arg)
327
327
328 def print_stack_trace(self, context=None):
328 def print_stack_trace(self, context=None):
329 if context is None:
329 if context is None:
330 context = self.context
330 context = self.context
331 try:
331 try:
332 context=int(context)
332 context=int(context)
333 if context <= 0:
333 if context <= 0:
334 raise ValueError("Context must be a positive integer")
334 raise ValueError("Context must be a positive integer")
335 except (TypeError, ValueError):
335 except (TypeError, ValueError):
336 raise ValueError("Context must be a positive integer")
336 raise ValueError("Context must be a positive integer")
337 try:
337 try:
338 for frame_lineno in self.stack:
338 for frame_lineno in self.stack:
339 self.print_stack_entry(frame_lineno, context=context)
339 self.print_stack_entry(frame_lineno, context=context)
340 except KeyboardInterrupt:
340 except KeyboardInterrupt:
341 pass
341 pass
342
342
343 def print_stack_entry(self,frame_lineno, prompt_prefix='\n-> ',
343 def print_stack_entry(self,frame_lineno, prompt_prefix='\n-> ',
344 context=None):
344 context=None):
345 if context is None:
345 if context is None:
346 context = self.context
346 context = self.context
347 try:
347 try:
348 context=int(context)
348 context=int(context)
349 if context <= 0:
349 if context <= 0:
350 raise ValueError("Context must be a positive integer")
350 raise ValueError("Context must be a positive integer")
351 except (TypeError, ValueError):
351 except (TypeError, ValueError):
352 raise ValueError("Context must be a positive integer")
352 raise ValueError("Context must be a positive integer")
353 print(self.format_stack_entry(frame_lineno, '', context))
353 print(self.format_stack_entry(frame_lineno, '', context))
354
354
355 # vds: >>
355 # vds: >>
356 frame, lineno = frame_lineno
356 frame, lineno = frame_lineno
357 filename = frame.f_code.co_filename
357 filename = frame.f_code.co_filename
358 self.shell.hooks.synchronize_with_editor(filename, lineno, 0)
358 self.shell.hooks.synchronize_with_editor(filename, lineno, 0)
359 # vds: <<
359 # vds: <<
360
360
361 def format_stack_entry(self, frame_lineno, lprefix=': ', context=None):
361 def format_stack_entry(self, frame_lineno, lprefix=': ', context=None):
362 if context is None:
362 if context is None:
363 context = self.context
363 context = self.context
364 try:
364 try:
365 context=int(context)
365 context=int(context)
366 if context <= 0:
366 if context <= 0:
367 print("Context must be a positive integer")
367 print("Context must be a positive integer")
368 except (TypeError, ValueError):
368 except (TypeError, ValueError):
369 print("Context must be a positive integer")
369 print("Context must be a positive integer")
370 try:
370 try:
371 import reprlib # Py 3
371 import reprlib # Py 3
372 except ImportError:
372 except ImportError:
373 import repr as reprlib # Py 2
373 import repr as reprlib # Py 2
374
374
375 ret = []
375 ret = []
376
376
377 Colors = self.color_scheme_table.active_colors
377 Colors = self.color_scheme_table.active_colors
378 ColorsNormal = Colors.Normal
378 ColorsNormal = Colors.Normal
379 tpl_link = u'%s%%s%s' % (Colors.filenameEm, ColorsNormal)
379 tpl_link = u'%s%%s%s' % (Colors.filenameEm, ColorsNormal)
380 tpl_call = u'%s%%s%s%%s%s' % (Colors.vName, Colors.valEm, ColorsNormal)
380 tpl_call = u'%s%%s%s%%s%s' % (Colors.vName, Colors.valEm, ColorsNormal)
381 tpl_line = u'%%s%s%%s %s%%s' % (Colors.lineno, ColorsNormal)
381 tpl_line = u'%%s%s%%s %s%%s' % (Colors.lineno, ColorsNormal)
382 tpl_line_em = u'%%s%s%%s %s%%s%s' % (Colors.linenoEm, Colors.line,
382 tpl_line_em = u'%%s%s%%s %s%%s%s' % (Colors.linenoEm, Colors.line,
383 ColorsNormal)
383 ColorsNormal)
384
384
385 frame, lineno = frame_lineno
385 frame, lineno = frame_lineno
386
386
387 return_value = ''
387 return_value = ''
388 if '__return__' in frame.f_locals:
388 if '__return__' in frame.f_locals:
389 rv = frame.f_locals['__return__']
389 rv = frame.f_locals['__return__']
390 #return_value += '->'
390 #return_value += '->'
391 return_value += reprlib.repr(rv) + '\n'
391 return_value += reprlib.repr(rv) + '\n'
392 ret.append(return_value)
392 ret.append(return_value)
393
393
394 #s = filename + '(' + `lineno` + ')'
394 #s = filename + '(' + `lineno` + ')'
395 filename = self.canonic(frame.f_code.co_filename)
395 filename = self.canonic(frame.f_code.co_filename)
396 link = tpl_link % py3compat.cast_unicode(filename)
396 link = tpl_link % py3compat.cast_unicode(filename)
397
397
398 if frame.f_code.co_name:
398 if frame.f_code.co_name:
399 func = frame.f_code.co_name
399 func = frame.f_code.co_name
400 else:
400 else:
401 func = "<lambda>"
401 func = "<lambda>"
402
402
403 call = ''
403 call = ''
404 if func != '?':
404 if func != '?':
405 if '__args__' in frame.f_locals:
405 if '__args__' in frame.f_locals:
406 args = reprlib.repr(frame.f_locals['__args__'])
406 args = reprlib.repr(frame.f_locals['__args__'])
407 else:
407 else:
408 args = '()'
408 args = '()'
409 call = tpl_call % (func, args)
409 call = tpl_call % (func, args)
410
410
411 # The level info should be generated in the same format pdb uses, to
411 # The level info should be generated in the same format pdb uses, to
412 # avoid breaking the pdbtrack functionality of python-mode in *emacs.
412 # avoid breaking the pdbtrack functionality of python-mode in *emacs.
413 if frame is self.curframe:
413 if frame is self.curframe:
414 ret.append('> ')
414 ret.append('> ')
415 else:
415 else:
416 ret.append(' ')
416 ret.append(' ')
417 ret.append(u'%s(%s)%s\n' % (link,lineno,call))
417 ret.append(u'%s(%s)%s\n' % (link,lineno,call))
418
418
419 start = lineno - 1 - context//2
419 start = lineno - 1 - context//2
420 lines = linecache.getlines(filename)
420 lines = linecache.getlines(filename)
421 start = min(start, len(lines) - context)
421 start = min(start, len(lines) - context)
422 start = max(start, 0)
422 start = max(start, 0)
423 lines = lines[start : start + context]
423 lines = lines[start : start + context]
424
424
425 for i,line in enumerate(lines):
425 for i,line in enumerate(lines):
426 show_arrow = (start + 1 + i == lineno)
426 show_arrow = (start + 1 + i == lineno)
427 linetpl = (frame is self.curframe or show_arrow) \
427 linetpl = (frame is self.curframe or show_arrow) \
428 and tpl_line_em \
428 and tpl_line_em \
429 or tpl_line
429 or tpl_line
430 ret.append(self.__format_line(linetpl, filename,
430 ret.append(self.__format_line(linetpl, filename,
431 start + 1 + i, line,
431 start + 1 + i, line,
432 arrow = show_arrow) )
432 arrow = show_arrow) )
433 return ''.join(ret)
433 return ''.join(ret)
434
434
435 def __format_line(self, tpl_line, filename, lineno, line, arrow = False):
435 def __format_line(self, tpl_line, filename, lineno, line, arrow = False):
436 bp_mark = ""
436 bp_mark = ""
437 bp_mark_color = ""
437 bp_mark_color = ""
438
438
439 new_line, err = self.parser.format2(line, 'str')
439 new_line, err = self.parser.format2(line, 'str')
440 if not err:
440 if not err:
441 line = new_line
441 line = new_line
442
442
443 bp = None
443 bp = None
444 if lineno in self.get_file_breaks(filename):
444 if lineno in self.get_file_breaks(filename):
445 bps = self.get_breaks(filename, lineno)
445 bps = self.get_breaks(filename, lineno)
446 bp = bps[-1]
446 bp = bps[-1]
447
447
448 if bp:
448 if bp:
449 Colors = self.color_scheme_table.active_colors
449 Colors = self.color_scheme_table.active_colors
450 bp_mark = str(bp.number)
450 bp_mark = str(bp.number)
451 bp_mark_color = Colors.breakpoint_enabled
451 bp_mark_color = Colors.breakpoint_enabled
452 if not bp.enabled:
452 if not bp.enabled:
453 bp_mark_color = Colors.breakpoint_disabled
453 bp_mark_color = Colors.breakpoint_disabled
454
454
455 numbers_width = 7
455 numbers_width = 7
456 if arrow:
456 if arrow:
457 # This is the line with the error
457 # This is the line with the error
458 pad = numbers_width - len(str(lineno)) - len(bp_mark)
458 pad = numbers_width - len(str(lineno)) - len(bp_mark)
459 num = '%s%s' % (make_arrow(pad), str(lineno))
459 num = '%s%s' % (make_arrow(pad), str(lineno))
460 else:
460 else:
461 num = '%*s' % (numbers_width - len(bp_mark), str(lineno))
461 num = '%*s' % (numbers_width - len(bp_mark), str(lineno))
462
462
463 return tpl_line % (bp_mark_color + bp_mark, num, line)
463 return tpl_line % (bp_mark_color + bp_mark, num, line)
464
464
465
465
466 def print_list_lines(self, filename, first, last):
466 def print_list_lines(self, filename, first, last):
467 """The printing (as opposed to the parsing part of a 'list'
467 """The printing (as opposed to the parsing part of a 'list'
468 command."""
468 command."""
469 try:
469 try:
470 Colors = self.color_scheme_table.active_colors
470 Colors = self.color_scheme_table.active_colors
471 ColorsNormal = Colors.Normal
471 ColorsNormal = Colors.Normal
472 tpl_line = '%%s%s%%s %s%%s' % (Colors.lineno, ColorsNormal)
472 tpl_line = '%%s%s%%s %s%%s' % (Colors.lineno, ColorsNormal)
473 tpl_line_em = '%%s%s%%s %s%%s%s' % (Colors.linenoEm, Colors.line, ColorsNormal)
473 tpl_line_em = '%%s%s%%s %s%%s%s' % (Colors.linenoEm, Colors.line, ColorsNormal)
474 src = []
474 src = []
475 if filename == "<string>" and hasattr(self, "_exec_filename"):
475 if filename == "<string>" and hasattr(self, "_exec_filename"):
476 filename = self._exec_filename
476 filename = self._exec_filename
477
477
478 for lineno in range(first, last+1):
478 for lineno in range(first, last+1):
479 line = linecache.getline(filename, lineno)
479 line = linecache.getline(filename, lineno)
480 if not line:
480 if not line:
481 break
481 break
482
482
483 if lineno == self.curframe.f_lineno:
483 if lineno == self.curframe.f_lineno:
484 line = self.__format_line(tpl_line_em, filename, lineno, line, arrow = True)
484 line = self.__format_line(tpl_line_em, filename, lineno, line, arrow = True)
485 else:
485 else:
486 line = self.__format_line(tpl_line, filename, lineno, line, arrow = False)
486 line = self.__format_line(tpl_line, filename, lineno, line, arrow = False)
487
487
488 src.append(line)
488 src.append(line)
489 self.lineno = lineno
489 self.lineno = lineno
490
490
491 print(''.join(src))
491 print(''.join(src))
492
492
493 except KeyboardInterrupt:
493 except KeyboardInterrupt:
494 pass
494 pass
495
495
496 def do_list(self, arg):
496 def do_list(self, arg):
497 """Print lines of code from the current stack frame
497 """Print lines of code from the current stack frame
498 """
498 """
499 self.lastcmd = 'list'
499 self.lastcmd = 'list'
500 last = None
500 last = None
501 if arg:
501 if arg:
502 try:
502 try:
503 x = eval(arg, {}, {})
503 x = eval(arg, {}, {})
504 if type(x) == type(()):
504 if type(x) == type(()):
505 first, last = x
505 first, last = x
506 first = int(first)
506 first = int(first)
507 last = int(last)
507 last = int(last)
508 if last < first:
508 if last < first:
509 # Assume it's a count
509 # Assume it's a count
510 last = first + last
510 last = first + last
511 else:
511 else:
512 first = max(1, int(x) - 5)
512 first = max(1, int(x) - 5)
513 except:
513 except:
514 print('*** Error in argument:', repr(arg))
514 print('*** Error in argument:', repr(arg))
515 return
515 return
516 elif self.lineno is None:
516 elif self.lineno is None:
517 first = max(1, self.curframe.f_lineno - 5)
517 first = max(1, self.curframe.f_lineno - 5)
518 else:
518 else:
519 first = self.lineno + 1
519 first = self.lineno + 1
520 if last is None:
520 if last is None:
521 last = first + 10
521 last = first + 10
522 self.print_list_lines(self.curframe.f_code.co_filename, first, last)
522 self.print_list_lines(self.curframe.f_code.co_filename, first, last)
523
523
524 # vds: >>
524 # vds: >>
525 lineno = first
525 lineno = first
526 filename = self.curframe.f_code.co_filename
526 filename = self.curframe.f_code.co_filename
527 self.shell.hooks.synchronize_with_editor(filename, lineno, 0)
527 self.shell.hooks.synchronize_with_editor(filename, lineno, 0)
528 # vds: <<
528 # vds: <<
529
529
530 do_l = do_list
530 do_l = do_list
531
531
532 def getsourcelines(self, obj):
532 def getsourcelines(self, obj):
533 lines, lineno = inspect.findsource(obj)
533 lines, lineno = inspect.findsource(obj)
534 if inspect.isframe(obj) and obj.f_globals is obj.f_locals:
534 if inspect.isframe(obj) and obj.f_globals is obj.f_locals:
535 # must be a module frame: do not try to cut a block out of it
535 # must be a module frame: do not try to cut a block out of it
536 return lines, 1
536 return lines, 1
537 elif inspect.ismodule(obj):
537 elif inspect.ismodule(obj):
538 return lines, 1
538 return lines, 1
539 return inspect.getblock(lines[lineno:]), lineno+1
539 return inspect.getblock(lines[lineno:]), lineno+1
540
540
541 def do_longlist(self, arg):
541 def do_longlist(self, arg):
542 """Print lines of code from the current stack frame.
542 """Print lines of code from the current stack frame.
543
543
544 Shows more lines than 'list' does.
544 Shows more lines than 'list' does.
545 """
545 """
546 self.lastcmd = 'longlist'
546 self.lastcmd = 'longlist'
547 try:
547 try:
548 lines, lineno = self.getsourcelines(self.curframe)
548 lines, lineno = self.getsourcelines(self.curframe)
549 except OSError as err:
549 except OSError as err:
550 self.error(err)
550 self.error(err)
551 return
551 return
552 last = lineno + len(lines)
552 last = lineno + len(lines)
553 self.print_list_lines(self.curframe.f_code.co_filename, lineno, last)
553 self.print_list_lines(self.curframe.f_code.co_filename, lineno, last)
554 do_ll = do_longlist
554 do_ll = do_longlist
555
555
556 def do_debug(self, arg):
556 def do_debug(self, arg):
557 """debug code
557 """debug code
558 Enter a recursive debugger that steps through the code
558 Enter a recursive debugger that steps through the code
559 argument (which is an arbitrary expression or statement to be
559 argument (which is an arbitrary expression or statement to be
560 executed in the current environment).
560 executed in the current environment).
561 """
561 """
562 sys.settrace(None)
562 sys.settrace(None)
563 globals = self.curframe.f_globals
563 globals = self.curframe.f_globals
564 locals = self.curframe_locals
564 locals = self.curframe_locals
565 p = self.__class__(completekey=self.completekey,
565 p = self.__class__(completekey=self.completekey,
566 stdin=self.stdin, stdout=self.stdout)
566 stdin=self.stdin, stdout=self.stdout)
567 p.use_rawinput = self.use_rawinput
567 p.use_rawinput = self.use_rawinput
568 p.prompt = "(%s) " % self.prompt.strip()
568 p.prompt = "(%s) " % self.prompt.strip()
569 self.message("ENTERING RECURSIVE DEBUGGER")
569 self.message("ENTERING RECURSIVE DEBUGGER")
570 sys.call_tracing(p.run, (arg, globals, locals))
570 sys.call_tracing(p.run, (arg, globals, locals))
571 self.message("LEAVING RECURSIVE DEBUGGER")
571 self.message("LEAVING RECURSIVE DEBUGGER")
572 sys.settrace(self.trace_dispatch)
572 sys.settrace(self.trace_dispatch)
573 self.lastcmd = p.lastcmd
573 self.lastcmd = p.lastcmd
574
574
575 def do_pdef(self, arg):
575 def do_pdef(self, arg):
576 """Print the call signature for any callable object.
576 """Print the call signature for any callable object.
577
577
578 The debugger interface to %pdef"""
578 The debugger interface to %pdef"""
579 namespaces = [('Locals', self.curframe.f_locals),
579 namespaces = [('Locals', self.curframe.f_locals),
580 ('Globals', self.curframe.f_globals)]
580 ('Globals', self.curframe.f_globals)]
581 self.shell.find_line_magic('pdef')(arg, namespaces=namespaces)
581 self.shell.find_line_magic('pdef')(arg, namespaces=namespaces)
582
582
583 def do_pdoc(self, arg):
583 def do_pdoc(self, arg):
584 """Print the docstring for an object.
584 """Print the docstring for an object.
585
585
586 The debugger interface to %pdoc."""
586 The debugger interface to %pdoc."""
587 namespaces = [('Locals', self.curframe.f_locals),
587 namespaces = [('Locals', self.curframe.f_locals),
588 ('Globals', self.curframe.f_globals)]
588 ('Globals', self.curframe.f_globals)]
589 self.shell.find_line_magic('pdoc')(arg, namespaces=namespaces)
589 self.shell.find_line_magic('pdoc')(arg, namespaces=namespaces)
590
590
591 def do_pfile(self, arg):
591 def do_pfile(self, arg):
592 """Print (or run through pager) the file where an object is defined.
592 """Print (or run through pager) the file where an object is defined.
593
593
594 The debugger interface to %pfile.
594 The debugger interface to %pfile.
595 """
595 """
596 namespaces = [('Locals', self.curframe.f_locals),
596 namespaces = [('Locals', self.curframe.f_locals),
597 ('Globals', self.curframe.f_globals)]
597 ('Globals', self.curframe.f_globals)]
598 self.shell.find_line_magic('pfile')(arg, namespaces=namespaces)
598 self.shell.find_line_magic('pfile')(arg, namespaces=namespaces)
599
599
600 def do_pinfo(self, arg):
600 def do_pinfo(self, arg):
601 """Provide detailed information about an object.
601 """Provide detailed information about an object.
602
602
603 The debugger interface to %pinfo, i.e., obj?."""
603 The debugger interface to %pinfo, i.e., obj?."""
604 namespaces = [('Locals', self.curframe.f_locals),
604 namespaces = [('Locals', self.curframe.f_locals),
605 ('Globals', self.curframe.f_globals)]
605 ('Globals', self.curframe.f_globals)]
606 self.shell.find_line_magic('pinfo')(arg, namespaces=namespaces)
606 self.shell.find_line_magic('pinfo')(arg, namespaces=namespaces)
607
607
608 def do_pinfo2(self, arg):
608 def do_pinfo2(self, arg):
609 """Provide extra detailed information about an object.
609 """Provide extra detailed information about an object.
610
610
611 The debugger interface to %pinfo2, i.e., obj??."""
611 The debugger interface to %pinfo2, i.e., obj??."""
612 namespaces = [('Locals', self.curframe.f_locals),
612 namespaces = [('Locals', self.curframe.f_locals),
613 ('Globals', self.curframe.f_globals)]
613 ('Globals', self.curframe.f_globals)]
614 self.shell.find_line_magic('pinfo2')(arg, namespaces=namespaces)
614 self.shell.find_line_magic('pinfo2')(arg, namespaces=namespaces)
615
615
616 def do_psource(self, arg):
616 def do_psource(self, arg):
617 """Print (or run through pager) the source code for an object."""
617 """Print (or run through pager) the source code for an object."""
618 namespaces = [('Locals', self.curframe.f_locals),
618 namespaces = [('Locals', self.curframe.f_locals),
619 ('Globals', self.curframe.f_globals)]
619 ('Globals', self.curframe.f_globals)]
620 self.shell.find_line_magic('psource')(arg, namespaces=namespaces)
620 self.shell.find_line_magic('psource')(arg, namespaces=namespaces)
621
621
622 def do_where(self, arg):
622 def do_where(self, arg):
623 """w(here)
623 """w(here)
624 Print a stack trace, with the most recent frame at the bottom.
624 Print a stack trace, with the most recent frame at the bottom.
625 An arrow indicates the "current frame", which determines the
625 An arrow indicates the "current frame", which determines the
626 context of most commands. 'bt' is an alias for this command.
626 context of most commands. 'bt' is an alias for this command.
627
627
628 Take a number as argument as an (optional) number of context line to
628 Take a number as argument as an (optional) number of context line to
629 print"""
629 print"""
630 if arg:
630 if arg:
631 context = int(arg)
631 context = int(arg)
632 self.print_stack_trace(context)
632 self.print_stack_trace(context)
633 else:
633 else:
634 self.print_stack_trace()
634 self.print_stack_trace()
635
635
636 do_w = do_where
636 do_w = do_where
637
637
638
638
639 def set_trace(frame=None):
639 def set_trace(frame=None):
640 """
640 """
641 Start debugging from `frame`.
641 Start debugging from `frame`.
642
642
643 If frame is not specified, debugging starts from caller's frame.
643 If frame is not specified, debugging starts from caller's frame.
644 """
644 """
645 Pdb().set_trace(frame or sys._getframe().f_back)
645 Pdb().set_trace(frame or sys._getframe().f_back)
@@ -1,1416 +1,1428 b''
1 # -*- coding: utf-8 -*-
1 # -*- coding: utf-8 -*-
2 """Top-level display functions for displaying object in different formats."""
2 """Top-level display functions for displaying object in different formats."""
3
3
4 # Copyright (c) IPython Development Team.
4 # Copyright (c) IPython Development Team.
5 # Distributed under the terms of the Modified BSD License.
5 # Distributed under the terms of the Modified BSD License.
6
6
7
7
8 from binascii import b2a_hex, b2a_base64, hexlify
8 from binascii import b2a_hex, b2a_base64, hexlify
9 import json
9 import json
10 import mimetypes
10 import mimetypes
11 import os
11 import os
12 import struct
12 import struct
13 import sys
13 import sys
14 import warnings
14 import warnings
15 from copy import deepcopy
15 from copy import deepcopy
16
16
17 from IPython.utils.py3compat import cast_unicode
17 from IPython.utils.py3compat import cast_unicode
18 from IPython.testing.skipdoctest import skip_doctest
18 from IPython.testing.skipdoctest import skip_doctest
19
19
20 __all__ = ['display', 'display_pretty', 'display_html', 'display_markdown',
20 __all__ = ['display', 'display_pretty', 'display_html', 'display_markdown',
21 'display_svg', 'display_png', 'display_jpeg', 'display_latex', 'display_json',
21 'display_svg', 'display_png', 'display_jpeg', 'display_latex', 'display_json',
22 'display_javascript', 'display_pdf', 'DisplayObject', 'TextDisplayObject',
22 'display_javascript', 'display_pdf', 'DisplayObject', 'TextDisplayObject',
23 'Pretty', 'HTML', 'Markdown', 'Math', 'Latex', 'SVG', 'ProgressBar', 'JSON',
23 'Pretty', 'HTML', 'Markdown', 'Math', 'Latex', 'SVG', 'ProgressBar', 'JSON',
24 'GeoJSON', 'Javascript', 'Image', 'clear_output', 'set_matplotlib_formats',
24 'GeoJSON', 'Javascript', 'Image', 'clear_output', 'set_matplotlib_formats',
25 'set_matplotlib_close', 'publish_display_data', 'update_display', 'DisplayHandle',
25 'set_matplotlib_close', 'publish_display_data', 'update_display', 'DisplayHandle',
26 'Video']
26 'Video']
27
27
28 #-----------------------------------------------------------------------------
28 #-----------------------------------------------------------------------------
29 # utility functions
29 # utility functions
30 #-----------------------------------------------------------------------------
30 #-----------------------------------------------------------------------------
31
31
32 def _safe_exists(path):
32 def _safe_exists(path):
33 """Check path, but don't let exceptions raise"""
33 """Check path, but don't let exceptions raise"""
34 try:
34 try:
35 return os.path.exists(path)
35 return os.path.exists(path)
36 except Exception:
36 except Exception:
37 return False
37 return False
38
38
39 def _merge(d1, d2):
39 def _merge(d1, d2):
40 """Like update, but merges sub-dicts instead of clobbering at the top level.
40 """Like update, but merges sub-dicts instead of clobbering at the top level.
41
41
42 Updates d1 in-place
42 Updates d1 in-place
43 """
43 """
44
44
45 if not isinstance(d2, dict) or not isinstance(d1, dict):
45 if not isinstance(d2, dict) or not isinstance(d1, dict):
46 return d2
46 return d2
47 for key, value in d2.items():
47 for key, value in d2.items():
48 d1[key] = _merge(d1.get(key), value)
48 d1[key] = _merge(d1.get(key), value)
49 return d1
49 return d1
50
50
51 def _display_mimetype(mimetype, objs, raw=False, metadata=None):
51 def _display_mimetype(mimetype, objs, raw=False, metadata=None):
52 """internal implementation of all display_foo methods
52 """internal implementation of all display_foo methods
53
53
54 Parameters
54 Parameters
55 ----------
55 ----------
56 mimetype : str
56 mimetype : str
57 The mimetype to be published (e.g. 'image/png')
57 The mimetype to be published (e.g. 'image/png')
58 objs : tuple of objects
58 objs : tuple of objects
59 The Python objects to display, or if raw=True raw text data to
59 The Python objects to display, or if raw=True raw text data to
60 display.
60 display.
61 raw : bool
61 raw : bool
62 Are the data objects raw data or Python objects that need to be
62 Are the data objects raw data or Python objects that need to be
63 formatted before display? [default: False]
63 formatted before display? [default: False]
64 metadata : dict (optional)
64 metadata : dict (optional)
65 Metadata to be associated with the specific mimetype output.
65 Metadata to be associated with the specific mimetype output.
66 """
66 """
67 if metadata:
67 if metadata:
68 metadata = {mimetype: metadata}
68 metadata = {mimetype: metadata}
69 if raw:
69 if raw:
70 # turn list of pngdata into list of { 'image/png': pngdata }
70 # turn list of pngdata into list of { 'image/png': pngdata }
71 objs = [ {mimetype: obj} for obj in objs ]
71 objs = [ {mimetype: obj} for obj in objs ]
72 display(*objs, raw=raw, metadata=metadata, include=[mimetype])
72 display(*objs, raw=raw, metadata=metadata, include=[mimetype])
73
73
74 #-----------------------------------------------------------------------------
74 #-----------------------------------------------------------------------------
75 # Main functions
75 # Main functions
76 #-----------------------------------------------------------------------------
76 #-----------------------------------------------------------------------------
77
77
78 # use * to indicate transient is keyword-only
78 # use * to indicate transient is keyword-only
79 def publish_display_data(data, metadata=None, source=None, *, transient=None, **kwargs):
79 def publish_display_data(data, metadata=None, source=None, *, transient=None, **kwargs):
80 """Publish data and metadata to all frontends.
80 """Publish data and metadata to all frontends.
81
81
82 See the ``display_data`` message in the messaging documentation for
82 See the ``display_data`` message in the messaging documentation for
83 more details about this message type.
83 more details about this message type.
84
84
85 Keys of data and metadata can be any mime-type.
85 Keys of data and metadata can be any mime-type.
86
86
87 Parameters
87 Parameters
88 ----------
88 ----------
89 data : dict
89 data : dict
90 A dictionary having keys that are valid MIME types (like
90 A dictionary having keys that are valid MIME types (like
91 'text/plain' or 'image/svg+xml') and values that are the data for
91 'text/plain' or 'image/svg+xml') and values that are the data for
92 that MIME type. The data itself must be a JSON'able data
92 that MIME type. The data itself must be a JSON'able data
93 structure. Minimally all data should have the 'text/plain' data,
93 structure. Minimally all data should have the 'text/plain' data,
94 which can be displayed by all frontends. If more than the plain
94 which can be displayed by all frontends. If more than the plain
95 text is given, it is up to the frontend to decide which
95 text is given, it is up to the frontend to decide which
96 representation to use.
96 representation to use.
97 metadata : dict
97 metadata : dict
98 A dictionary for metadata related to the data. This can contain
98 A dictionary for metadata related to the data. This can contain
99 arbitrary key, value pairs that frontends can use to interpret
99 arbitrary key, value pairs that frontends can use to interpret
100 the data. mime-type keys matching those in data can be used
100 the data. mime-type keys matching those in data can be used
101 to specify metadata about particular representations.
101 to specify metadata about particular representations.
102 source : str, deprecated
102 source : str, deprecated
103 Unused.
103 Unused.
104 transient : dict, keyword-only
104 transient : dict, keyword-only
105 A dictionary of transient data, such as display_id.
105 A dictionary of transient data, such as display_id.
106 """
106 """
107 from IPython.core.interactiveshell import InteractiveShell
107 from IPython.core.interactiveshell import InteractiveShell
108
108
109 display_pub = InteractiveShell.instance().display_pub
109 display_pub = InteractiveShell.instance().display_pub
110
110
111 # only pass transient if supplied,
111 # only pass transient if supplied,
112 # to avoid errors with older ipykernel.
112 # to avoid errors with older ipykernel.
113 # TODO: We could check for ipykernel version and provide a detailed upgrade message.
113 # TODO: We could check for ipykernel version and provide a detailed upgrade message.
114 if transient:
114 if transient:
115 kwargs['transient'] = transient
115 kwargs['transient'] = transient
116
116
117 display_pub.publish(
117 display_pub.publish(
118 data=data,
118 data=data,
119 metadata=metadata,
119 metadata=metadata,
120 **kwargs
120 **kwargs
121 )
121 )
122
122
123
123
124 def _new_id():
124 def _new_id():
125 """Generate a new random text id with urandom"""
125 """Generate a new random text id with urandom"""
126 return b2a_hex(os.urandom(16)).decode('ascii')
126 return b2a_hex(os.urandom(16)).decode('ascii')
127
127
128
128
129 def display(*objs, include=None, exclude=None, metadata=None, transient=None, display_id=None, **kwargs):
129 def display(*objs, include=None, exclude=None, metadata=None, transient=None, display_id=None, **kwargs):
130 """Display a Python object in all frontends.
130 """Display a Python object in all frontends.
131
131
132 By default all representations will be computed and sent to the frontends.
132 By default all representations will be computed and sent to the frontends.
133 Frontends can decide which representation is used and how.
133 Frontends can decide which representation is used and how.
134
134
135 In terminal IPython this will be similar to using :func:`print`, for use in richer
135 In terminal IPython this will be similar to using :func:`print`, for use in richer
136 frontends see Jupyter notebook examples with rich display logic.
136 frontends see Jupyter notebook examples with rich display logic.
137
137
138 Parameters
138 Parameters
139 ----------
139 ----------
140 objs : tuple of objects
140 objs : tuple of objects
141 The Python objects to display.
141 The Python objects to display.
142 raw : bool, optional
142 raw : bool, optional
143 Are the objects to be displayed already mimetype-keyed dicts of raw display data,
143 Are the objects to be displayed already mimetype-keyed dicts of raw display data,
144 or Python objects that need to be formatted before display? [default: False]
144 or Python objects that need to be formatted before display? [default: False]
145 include : list, tuple or set, optional
145 include : list, tuple or set, optional
146 A list of format type strings (MIME types) to include in the
146 A list of format type strings (MIME types) to include in the
147 format data dict. If this is set *only* the format types included
147 format data dict. If this is set *only* the format types included
148 in this list will be computed.
148 in this list will be computed.
149 exclude : list, tuple or set, optional
149 exclude : list, tuple or set, optional
150 A list of format type strings (MIME types) to exclude in the format
150 A list of format type strings (MIME types) to exclude in the format
151 data dict. If this is set all format types will be computed,
151 data dict. If this is set all format types will be computed,
152 except for those included in this argument.
152 except for those included in this argument.
153 metadata : dict, optional
153 metadata : dict, optional
154 A dictionary of metadata to associate with the output.
154 A dictionary of metadata to associate with the output.
155 mime-type keys in this dictionary will be associated with the individual
155 mime-type keys in this dictionary will be associated with the individual
156 representation formats, if they exist.
156 representation formats, if they exist.
157 transient : dict, optional
157 transient : dict, optional
158 A dictionary of transient data to associate with the output.
158 A dictionary of transient data to associate with the output.
159 Data in this dict should not be persisted to files (e.g. notebooks).
159 Data in this dict should not be persisted to files (e.g. notebooks).
160 display_id : str, bool optional
160 display_id : str, bool optional
161 Set an id for the display.
161 Set an id for the display.
162 This id can be used for updating this display area later via update_display.
162 This id can be used for updating this display area later via update_display.
163 If given as `True`, generate a new `display_id`
163 If given as `True`, generate a new `display_id`
164 kwargs: additional keyword-args, optional
164 kwargs: additional keyword-args, optional
165 Additional keyword-arguments are passed through to the display publisher.
165 Additional keyword-arguments are passed through to the display publisher.
166
166
167 Returns
167 Returns
168 -------
168 -------
169
169
170 handle: DisplayHandle
170 handle: DisplayHandle
171 Returns a handle on updatable displays for use with :func:`update_display`,
171 Returns a handle on updatable displays for use with :func:`update_display`,
172 if `display_id` is given. Returns :any:`None` if no `display_id` is given
172 if `display_id` is given. Returns :any:`None` if no `display_id` is given
173 (default).
173 (default).
174
174
175 Examples
175 Examples
176 --------
176 --------
177
177
178 >>> class Json(object):
178 >>> class Json(object):
179 ... def __init__(self, json):
179 ... def __init__(self, json):
180 ... self.json = json
180 ... self.json = json
181 ... def _repr_pretty_(self, pp, cycle):
181 ... def _repr_pretty_(self, pp, cycle):
182 ... import json
182 ... import json
183 ... pp.text(json.dumps(self.json, indent=2))
183 ... pp.text(json.dumps(self.json, indent=2))
184 ... def __repr__(self):
184 ... def __repr__(self):
185 ... return str(self.json)
185 ... return str(self.json)
186 ...
186 ...
187
187
188 >>> d = Json({1:2, 3: {4:5}})
188 >>> d = Json({1:2, 3: {4:5}})
189
189
190 >>> print(d)
190 >>> print(d)
191 {1: 2, 3: {4: 5}}
191 {1: 2, 3: {4: 5}}
192
192
193 >>> display(d)
193 >>> display(d)
194 {
194 {
195 "1": 2,
195 "1": 2,
196 "3": {
196 "3": {
197 "4": 5
197 "4": 5
198 }
198 }
199 }
199 }
200
200
201 >>> def int_formatter(integer, pp, cycle):
201 >>> def int_formatter(integer, pp, cycle):
202 ... pp.text('I'*integer)
202 ... pp.text('I'*integer)
203
203
204 >>> plain = get_ipython().display_formatter.formatters['text/plain']
204 >>> plain = get_ipython().display_formatter.formatters['text/plain']
205 >>> plain.for_type(int, int_formatter)
205 >>> plain.for_type(int, int_formatter)
206 <function _repr_pprint at 0x...>
206 <function _repr_pprint at 0x...>
207 >>> display(7-5)
207 >>> display(7-5)
208 II
208 II
209
209
210 >>> del plain.type_printers[int]
210 >>> del plain.type_printers[int]
211 >>> display(7-5)
211 >>> display(7-5)
212 2
212 2
213
213
214 See Also
214 See Also
215 --------
215 --------
216
216
217 :func:`update_display`
217 :func:`update_display`
218
218
219 Notes
219 Notes
220 -----
220 -----
221
221
222 In Python, objects can declare their textual representation using the
222 In Python, objects can declare their textual representation using the
223 `__repr__` method. IPython expands on this idea and allows objects to declare
223 `__repr__` method. IPython expands on this idea and allows objects to declare
224 other, rich representations including:
224 other, rich representations including:
225
225
226 - HTML
226 - HTML
227 - JSON
227 - JSON
228 - PNG
228 - PNG
229 - JPEG
229 - JPEG
230 - SVG
230 - SVG
231 - LaTeX
231 - LaTeX
232
232
233 A single object can declare some or all of these representations; all are
233 A single object can declare some or all of these representations; all are
234 handled by IPython's display system.
234 handled by IPython's display system.
235
235
236 The main idea of the first approach is that you have to implement special
236 The main idea of the first approach is that you have to implement special
237 display methods when you define your class, one for each representation you
237 display methods when you define your class, one for each representation you
238 want to use. Here is a list of the names of the special methods and the
238 want to use. Here is a list of the names of the special methods and the
239 values they must return:
239 values they must return:
240
240
241 - `_repr_html_`: return raw HTML as a string
241 - `_repr_html_`: return raw HTML as a string
242 - `_repr_json_`: return a JSONable dict
242 - `_repr_json_`: return a JSONable dict
243 - `_repr_jpeg_`: return raw JPEG data
243 - `_repr_jpeg_`: return raw JPEG data
244 - `_repr_png_`: return raw PNG data
244 - `_repr_png_`: return raw PNG data
245 - `_repr_svg_`: return raw SVG data as a string
245 - `_repr_svg_`: return raw SVG data as a string
246 - `_repr_latex_`: return LaTeX commands in a string surrounded by "$".
246 - `_repr_latex_`: return LaTeX commands in a string surrounded by "$".
247 - `_repr_mimebundle_`: return a full mimebundle containing the mapping
247 - `_repr_mimebundle_`: return a full mimebundle containing the mapping
248 from all mimetypes to data.
248 from all mimetypes to data.
249 Use this for any mime-type not listed above.
249 Use this for any mime-type not listed above.
250
250
251 When you are directly writing your own classes, you can adapt them for
251 When you are directly writing your own classes, you can adapt them for
252 display in IPython by following the above approach. But in practice, you
252 display in IPython by following the above approach. But in practice, you
253 often need to work with existing classes that you can't easily modify.
253 often need to work with existing classes that you can't easily modify.
254
254
255 You can refer to the documentation on integrating with the display system in
255 You can refer to the documentation on integrating with the display system in
256 order to register custom formatters for already existing types
256 order to register custom formatters for already existing types
257 (:ref:`integrating_rich_display`).
257 (:ref:`integrating_rich_display`).
258
258
259 .. versionadded:: 5.4 display available without import
259 .. versionadded:: 5.4 display available without import
260 .. versionadded:: 6.1 display available without import
260 .. versionadded:: 6.1 display available without import
261
261
262 Since IPython 5.4 and 6.1 :func:`display` is automatically made available to
262 Since IPython 5.4 and 6.1 :func:`display` is automatically made available to
263 the user without import. If you are using display in a document that might
263 the user without import. If you are using display in a document that might
264 be used in a pure python context or with older version of IPython, use the
264 be used in a pure python context or with older version of IPython, use the
265 following import at the top of your file::
265 following import at the top of your file::
266
266
267 from IPython.display import display
267 from IPython.display import display
268
268
269 """
269 """
270 from IPython.core.interactiveshell import InteractiveShell
270 from IPython.core.interactiveshell import InteractiveShell
271
271
272 if not InteractiveShell.initialized():
272 if not InteractiveShell.initialized():
273 # Directly print objects.
273 # Directly print objects.
274 print(*objs)
274 print(*objs)
275 return
275 return
276
276
277 raw = kwargs.pop('raw', False)
277 raw = kwargs.pop('raw', False)
278 if transient is None:
278 if transient is None:
279 transient = {}
279 transient = {}
280 if metadata is None:
280 if metadata is None:
281 metadata={}
281 metadata={}
282 if display_id:
282 if display_id:
283 if display_id is True:
283 if display_id is True:
284 display_id = _new_id()
284 display_id = _new_id()
285 transient['display_id'] = display_id
285 transient['display_id'] = display_id
286 if kwargs.get('update') and 'display_id' not in transient:
286 if kwargs.get('update') and 'display_id' not in transient:
287 raise TypeError('display_id required for update_display')
287 raise TypeError('display_id required for update_display')
288 if transient:
288 if transient:
289 kwargs['transient'] = transient
289 kwargs['transient'] = transient
290
290
291 if not raw:
291 if not raw:
292 format = InteractiveShell.instance().display_formatter.format
292 format = InteractiveShell.instance().display_formatter.format
293
293
294 for obj in objs:
294 for obj in objs:
295 if raw:
295 if raw:
296 publish_display_data(data=obj, metadata=metadata, **kwargs)
296 publish_display_data(data=obj, metadata=metadata, **kwargs)
297 else:
297 else:
298 format_dict, md_dict = format(obj, include=include, exclude=exclude)
298 format_dict, md_dict = format(obj, include=include, exclude=exclude)
299 if not format_dict:
299 if not format_dict:
300 # nothing to display (e.g. _ipython_display_ took over)
300 # nothing to display (e.g. _ipython_display_ took over)
301 continue
301 continue
302 if metadata:
302 if metadata:
303 # kwarg-specified metadata gets precedence
303 # kwarg-specified metadata gets precedence
304 _merge(md_dict, metadata)
304 _merge(md_dict, metadata)
305 publish_display_data(data=format_dict, metadata=md_dict, **kwargs)
305 publish_display_data(data=format_dict, metadata=md_dict, **kwargs)
306 if display_id:
306 if display_id:
307 return DisplayHandle(display_id)
307 return DisplayHandle(display_id)
308
308
309
309
310 # use * for keyword-only display_id arg
310 # use * for keyword-only display_id arg
311 def update_display(obj, *, display_id, **kwargs):
311 def update_display(obj, *, display_id, **kwargs):
312 """Update an existing display by id
312 """Update an existing display by id
313
313
314 Parameters
314 Parameters
315 ----------
315 ----------
316
316
317 obj:
317 obj:
318 The object with which to update the display
318 The object with which to update the display
319 display_id: keyword-only
319 display_id: keyword-only
320 The id of the display to update
320 The id of the display to update
321
321
322 See Also
322 See Also
323 --------
323 --------
324
324
325 :func:`display`
325 :func:`display`
326 """
326 """
327 kwargs['update'] = True
327 kwargs['update'] = True
328 display(obj, display_id=display_id, **kwargs)
328 display(obj, display_id=display_id, **kwargs)
329
329
330
330
331 class DisplayHandle(object):
331 class DisplayHandle(object):
332 """A handle on an updatable display
332 """A handle on an updatable display
333
333
334 Call `.update(obj)` to display a new object.
334 Call `.update(obj)` to display a new object.
335
335
336 Call `.display(obj`) to add a new instance of this display,
336 Call `.display(obj`) to add a new instance of this display,
337 and update existing instances.
337 and update existing instances.
338
338
339 See Also
339 See Also
340 --------
340 --------
341
341
342 :func:`display`, :func:`update_display`
342 :func:`display`, :func:`update_display`
343
343
344 """
344 """
345
345
346 def __init__(self, display_id=None):
346 def __init__(self, display_id=None):
347 if display_id is None:
347 if display_id is None:
348 display_id = _new_id()
348 display_id = _new_id()
349 self.display_id = display_id
349 self.display_id = display_id
350
350
351 def __repr__(self):
351 def __repr__(self):
352 return "<%s display_id=%s>" % (self.__class__.__name__, self.display_id)
352 return "<%s display_id=%s>" % (self.__class__.__name__, self.display_id)
353
353
354 def display(self, obj, **kwargs):
354 def display(self, obj, **kwargs):
355 """Make a new display with my id, updating existing instances.
355 """Make a new display with my id, updating existing instances.
356
356
357 Parameters
357 Parameters
358 ----------
358 ----------
359
359
360 obj:
360 obj:
361 object to display
361 object to display
362 **kwargs:
362 **kwargs:
363 additional keyword arguments passed to display
363 additional keyword arguments passed to display
364 """
364 """
365 display(obj, display_id=self.display_id, **kwargs)
365 display(obj, display_id=self.display_id, **kwargs)
366
366
367 def update(self, obj, **kwargs):
367 def update(self, obj, **kwargs):
368 """Update existing displays with my id
368 """Update existing displays with my id
369
369
370 Parameters
370 Parameters
371 ----------
371 ----------
372
372
373 obj:
373 obj:
374 object to display
374 object to display
375 **kwargs:
375 **kwargs:
376 additional keyword arguments passed to update_display
376 additional keyword arguments passed to update_display
377 """
377 """
378 update_display(obj, display_id=self.display_id, **kwargs)
378 update_display(obj, display_id=self.display_id, **kwargs)
379
379
380
380
381 def display_pretty(*objs, **kwargs):
381 def display_pretty(*objs, **kwargs):
382 """Display the pretty (default) representation of an object.
382 """Display the pretty (default) representation of an object.
383
383
384 Parameters
384 Parameters
385 ----------
385 ----------
386 objs : tuple of objects
386 objs : tuple of objects
387 The Python objects to display, or if raw=True raw text data to
387 The Python objects to display, or if raw=True raw text data to
388 display.
388 display.
389 raw : bool
389 raw : bool
390 Are the data objects raw data or Python objects that need to be
390 Are the data objects raw data or Python objects that need to be
391 formatted before display? [default: False]
391 formatted before display? [default: False]
392 metadata : dict (optional)
392 metadata : dict (optional)
393 Metadata to be associated with the specific mimetype output.
393 Metadata to be associated with the specific mimetype output.
394 """
394 """
395 _display_mimetype('text/plain', objs, **kwargs)
395 _display_mimetype('text/plain', objs, **kwargs)
396
396
397
397
398 def display_html(*objs, **kwargs):
398 def display_html(*objs, **kwargs):
399 """Display the HTML representation of an object.
399 """Display the HTML representation of an object.
400
400
401 Note: If raw=False and the object does not have a HTML
401 Note: If raw=False and the object does not have a HTML
402 representation, no HTML will be shown.
402 representation, no HTML will be shown.
403
403
404 Parameters
404 Parameters
405 ----------
405 ----------
406 objs : tuple of objects
406 objs : tuple of objects
407 The Python objects to display, or if raw=True raw HTML data to
407 The Python objects to display, or if raw=True raw HTML data to
408 display.
408 display.
409 raw : bool
409 raw : bool
410 Are the data objects raw data or Python objects that need to be
410 Are the data objects raw data or Python objects that need to be
411 formatted before display? [default: False]
411 formatted before display? [default: False]
412 metadata : dict (optional)
412 metadata : dict (optional)
413 Metadata to be associated with the specific mimetype output.
413 Metadata to be associated with the specific mimetype output.
414 """
414 """
415 _display_mimetype('text/html', objs, **kwargs)
415 _display_mimetype('text/html', objs, **kwargs)
416
416
417
417
418 def display_markdown(*objs, **kwargs):
418 def display_markdown(*objs, **kwargs):
419 """Displays the Markdown representation of an object.
419 """Displays the Markdown representation of an object.
420
420
421 Parameters
421 Parameters
422 ----------
422 ----------
423 objs : tuple of objects
423 objs : tuple of objects
424 The Python objects to display, or if raw=True raw markdown data to
424 The Python objects to display, or if raw=True raw markdown data to
425 display.
425 display.
426 raw : bool
426 raw : bool
427 Are the data objects raw data or Python objects that need to be
427 Are the data objects raw data or Python objects that need to be
428 formatted before display? [default: False]
428 formatted before display? [default: False]
429 metadata : dict (optional)
429 metadata : dict (optional)
430 Metadata to be associated with the specific mimetype output.
430 Metadata to be associated with the specific mimetype output.
431 """
431 """
432
432
433 _display_mimetype('text/markdown', objs, **kwargs)
433 _display_mimetype('text/markdown', objs, **kwargs)
434
434
435
435
436 def display_svg(*objs, **kwargs):
436 def display_svg(*objs, **kwargs):
437 """Display the SVG representation of an object.
437 """Display the SVG representation of an object.
438
438
439 Parameters
439 Parameters
440 ----------
440 ----------
441 objs : tuple of objects
441 objs : tuple of objects
442 The Python objects to display, or if raw=True raw svg data to
442 The Python objects to display, or if raw=True raw svg data to
443 display.
443 display.
444 raw : bool
444 raw : bool
445 Are the data objects raw data or Python objects that need to be
445 Are the data objects raw data or Python objects that need to be
446 formatted before display? [default: False]
446 formatted before display? [default: False]
447 metadata : dict (optional)
447 metadata : dict (optional)
448 Metadata to be associated with the specific mimetype output.
448 Metadata to be associated with the specific mimetype output.
449 """
449 """
450 _display_mimetype('image/svg+xml', objs, **kwargs)
450 _display_mimetype('image/svg+xml', objs, **kwargs)
451
451
452
452
453 def display_png(*objs, **kwargs):
453 def display_png(*objs, **kwargs):
454 """Display the PNG representation of an object.
454 """Display the PNG representation of an object.
455
455
456 Parameters
456 Parameters
457 ----------
457 ----------
458 objs : tuple of objects
458 objs : tuple of objects
459 The Python objects to display, or if raw=True raw png data to
459 The Python objects to display, or if raw=True raw png data to
460 display.
460 display.
461 raw : bool
461 raw : bool
462 Are the data objects raw data or Python objects that need to be
462 Are the data objects raw data or Python objects that need to be
463 formatted before display? [default: False]
463 formatted before display? [default: False]
464 metadata : dict (optional)
464 metadata : dict (optional)
465 Metadata to be associated with the specific mimetype output.
465 Metadata to be associated with the specific mimetype output.
466 """
466 """
467 _display_mimetype('image/png', objs, **kwargs)
467 _display_mimetype('image/png', objs, **kwargs)
468
468
469
469
470 def display_jpeg(*objs, **kwargs):
470 def display_jpeg(*objs, **kwargs):
471 """Display the JPEG representation of an object.
471 """Display the JPEG representation of an object.
472
472
473 Parameters
473 Parameters
474 ----------
474 ----------
475 objs : tuple of objects
475 objs : tuple of objects
476 The Python objects to display, or if raw=True raw JPEG data to
476 The Python objects to display, or if raw=True raw JPEG data to
477 display.
477 display.
478 raw : bool
478 raw : bool
479 Are the data objects raw data or Python objects that need to be
479 Are the data objects raw data or Python objects that need to be
480 formatted before display? [default: False]
480 formatted before display? [default: False]
481 metadata : dict (optional)
481 metadata : dict (optional)
482 Metadata to be associated with the specific mimetype output.
482 Metadata to be associated with the specific mimetype output.
483 """
483 """
484 _display_mimetype('image/jpeg', objs, **kwargs)
484 _display_mimetype('image/jpeg', objs, **kwargs)
485
485
486
486
487 def display_latex(*objs, **kwargs):
487 def display_latex(*objs, **kwargs):
488 """Display the LaTeX representation of an object.
488 """Display the LaTeX representation of an object.
489
489
490 Parameters
490 Parameters
491 ----------
491 ----------
492 objs : tuple of objects
492 objs : tuple of objects
493 The Python objects to display, or if raw=True raw latex data to
493 The Python objects to display, or if raw=True raw latex data to
494 display.
494 display.
495 raw : bool
495 raw : bool
496 Are the data objects raw data or Python objects that need to be
496 Are the data objects raw data or Python objects that need to be
497 formatted before display? [default: False]
497 formatted before display? [default: False]
498 metadata : dict (optional)
498 metadata : dict (optional)
499 Metadata to be associated with the specific mimetype output.
499 Metadata to be associated with the specific mimetype output.
500 """
500 """
501 _display_mimetype('text/latex', objs, **kwargs)
501 _display_mimetype('text/latex', objs, **kwargs)
502
502
503
503
504 def display_json(*objs, **kwargs):
504 def display_json(*objs, **kwargs):
505 """Display the JSON representation of an object.
505 """Display the JSON representation of an object.
506
506
507 Note that not many frontends support displaying JSON.
507 Note that not many frontends support displaying JSON.
508
508
509 Parameters
509 Parameters
510 ----------
510 ----------
511 objs : tuple of objects
511 objs : tuple of objects
512 The Python objects to display, or if raw=True raw json data to
512 The Python objects to display, or if raw=True raw json data to
513 display.
513 display.
514 raw : bool
514 raw : bool
515 Are the data objects raw data or Python objects that need to be
515 Are the data objects raw data or Python objects that need to be
516 formatted before display? [default: False]
516 formatted before display? [default: False]
517 metadata : dict (optional)
517 metadata : dict (optional)
518 Metadata to be associated with the specific mimetype output.
518 Metadata to be associated with the specific mimetype output.
519 """
519 """
520 _display_mimetype('application/json', objs, **kwargs)
520 _display_mimetype('application/json', objs, **kwargs)
521
521
522
522
523 def display_javascript(*objs, **kwargs):
523 def display_javascript(*objs, **kwargs):
524 """Display the Javascript representation of an object.
524 """Display the Javascript representation of an object.
525
525
526 Parameters
526 Parameters
527 ----------
527 ----------
528 objs : tuple of objects
528 objs : tuple of objects
529 The Python objects to display, or if raw=True raw javascript data to
529 The Python objects to display, or if raw=True raw javascript data to
530 display.
530 display.
531 raw : bool
531 raw : bool
532 Are the data objects raw data or Python objects that need to be
532 Are the data objects raw data or Python objects that need to be
533 formatted before display? [default: False]
533 formatted before display? [default: False]
534 metadata : dict (optional)
534 metadata : dict (optional)
535 Metadata to be associated with the specific mimetype output.
535 Metadata to be associated with the specific mimetype output.
536 """
536 """
537 _display_mimetype('application/javascript', objs, **kwargs)
537 _display_mimetype('application/javascript', objs, **kwargs)
538
538
539
539
540 def display_pdf(*objs, **kwargs):
540 def display_pdf(*objs, **kwargs):
541 """Display the PDF representation of an object.
541 """Display the PDF representation of an object.
542
542
543 Parameters
543 Parameters
544 ----------
544 ----------
545 objs : tuple of objects
545 objs : tuple of objects
546 The Python objects to display, or if raw=True raw javascript data to
546 The Python objects to display, or if raw=True raw javascript data to
547 display.
547 display.
548 raw : bool
548 raw : bool
549 Are the data objects raw data or Python objects that need to be
549 Are the data objects raw data or Python objects that need to be
550 formatted before display? [default: False]
550 formatted before display? [default: False]
551 metadata : dict (optional)
551 metadata : dict (optional)
552 Metadata to be associated with the specific mimetype output.
552 Metadata to be associated with the specific mimetype output.
553 """
553 """
554 _display_mimetype('application/pdf', objs, **kwargs)
554 _display_mimetype('application/pdf', objs, **kwargs)
555
555
556
556
557 #-----------------------------------------------------------------------------
557 #-----------------------------------------------------------------------------
558 # Smart classes
558 # Smart classes
559 #-----------------------------------------------------------------------------
559 #-----------------------------------------------------------------------------
560
560
561
561
562 class DisplayObject(object):
562 class DisplayObject(object):
563 """An object that wraps data to be displayed."""
563 """An object that wraps data to be displayed."""
564
564
565 _read_flags = 'r'
565 _read_flags = 'r'
566 _show_mem_addr = False
566 _show_mem_addr = False
567 metadata = None
567 metadata = None
568
568
569 def __init__(self, data=None, url=None, filename=None, metadata=None):
569 def __init__(self, data=None, url=None, filename=None, metadata=None):
570 """Create a display object given raw data.
570 """Create a display object given raw data.
571
571
572 When this object is returned by an expression or passed to the
572 When this object is returned by an expression or passed to the
573 display function, it will result in the data being displayed
573 display function, it will result in the data being displayed
574 in the frontend. The MIME type of the data should match the
574 in the frontend. The MIME type of the data should match the
575 subclasses used, so the Png subclass should be used for 'image/png'
575 subclasses used, so the Png subclass should be used for 'image/png'
576 data. If the data is a URL, the data will first be downloaded
576 data. If the data is a URL, the data will first be downloaded
577 and then displayed. If
577 and then displayed. If
578
578
579 Parameters
579 Parameters
580 ----------
580 ----------
581 data : unicode, str or bytes
581 data : unicode, str or bytes
582 The raw data or a URL or file to load the data from
582 The raw data or a URL or file to load the data from
583 url : unicode
583 url : unicode
584 A URL to download the data from.
584 A URL to download the data from.
585 filename : unicode
585 filename : unicode
586 Path to a local file to load the data from.
586 Path to a local file to load the data from.
587 metadata : dict
587 metadata : dict
588 Dict of metadata associated to be the object when displayed
588 Dict of metadata associated to be the object when displayed
589 """
589 """
590 if data is not None and isinstance(data, str):
590 if data is not None and isinstance(data, str):
591 if data.startswith('http') and url is None:
591 if data.startswith('http') and url is None:
592 url = data
592 url = data
593 filename = None
593 filename = None
594 data = None
594 data = None
595 elif _safe_exists(data) and filename is None:
595 elif _safe_exists(data) and filename is None:
596 url = None
596 url = None
597 filename = data
597 filename = data
598 data = None
598 data = None
599
599
600 self.data = data
600 self.data = data
601 self.url = url
601 self.url = url
602 self.filename = filename
602 self.filename = filename
603
603
604 if metadata is not None:
604 if metadata is not None:
605 self.metadata = metadata
605 self.metadata = metadata
606 elif self.metadata is None:
606 elif self.metadata is None:
607 self.metadata = {}
607 self.metadata = {}
608
608
609 self.reload()
609 self.reload()
610 self._check_data()
610 self._check_data()
611
611
612 def __repr__(self):
612 def __repr__(self):
613 if not self._show_mem_addr:
613 if not self._show_mem_addr:
614 cls = self.__class__
614 cls = self.__class__
615 r = "<%s.%s object>" % (cls.__module__, cls.__name__)
615 r = "<%s.%s object>" % (cls.__module__, cls.__name__)
616 else:
616 else:
617 r = super(DisplayObject, self).__repr__()
617 r = super(DisplayObject, self).__repr__()
618 return r
618 return r
619
619
620 def _check_data(self):
620 def _check_data(self):
621 """Override in subclasses if there's something to check."""
621 """Override in subclasses if there's something to check."""
622 pass
622 pass
623
623
624 def _data_and_metadata(self):
624 def _data_and_metadata(self):
625 """shortcut for returning metadata with shape information, if defined"""
625 """shortcut for returning metadata with shape information, if defined"""
626 if self.metadata:
626 if self.metadata:
627 return self.data, deepcopy(self.metadata)
627 return self.data, deepcopy(self.metadata)
628 else:
628 else:
629 return self.data
629 return self.data
630
630
631 def reload(self):
631 def reload(self):
632 """Reload the raw data from file or URL."""
632 """Reload the raw data from file or URL."""
633 if self.filename is not None:
633 if self.filename is not None:
634 with open(self.filename, self._read_flags) as f:
634 with open(self.filename, self._read_flags) as f:
635 self.data = f.read()
635 self.data = f.read()
636 elif self.url is not None:
636 elif self.url is not None:
637 try:
637 try:
638 # Deferred import
638 # Deferred import
639 from urllib.request import urlopen
639 from urllib.request import urlopen
640 response = urlopen(self.url)
640 response = urlopen(self.url)
641 self.data = response.read()
641 self.data = response.read()
642 # extract encoding from header, if there is one:
642 # extract encoding from header, if there is one:
643 encoding = None
643 encoding = None
644 for sub in response.headers['content-type'].split(';'):
644 for sub in response.headers['content-type'].split(';'):
645 sub = sub.strip()
645 sub = sub.strip()
646 if sub.startswith('charset'):
646 if sub.startswith('charset'):
647 encoding = sub.split('=')[-1].strip()
647 encoding = sub.split('=')[-1].strip()
648 break
648 break
649 # decode data, if an encoding was specified
649 # decode data, if an encoding was specified
650 if encoding:
650 if encoding:
651 self.data = self.data.decode(encoding, 'replace')
651 self.data = self.data.decode(encoding, 'replace')
652 except:
652 except:
653 self.data = None
653 self.data = None
654
654
655 class TextDisplayObject(DisplayObject):
655 class TextDisplayObject(DisplayObject):
656 """Validate that display data is text"""
656 """Validate that display data is text"""
657 def _check_data(self):
657 def _check_data(self):
658 if self.data is not None and not isinstance(self.data, str):
658 if self.data is not None and not isinstance(self.data, str):
659 raise TypeError("%s expects text, not %r" % (self.__class__.__name__, self.data))
659 raise TypeError("%s expects text, not %r" % (self.__class__.__name__, self.data))
660
660
661 class Pretty(TextDisplayObject):
661 class Pretty(TextDisplayObject):
662
662
663 def _repr_pretty_(self, pp, cycle):
663 def _repr_pretty_(self, pp, cycle):
664 return pp.text(self.data)
664 return pp.text(self.data)
665
665
666
666
667 class HTML(TextDisplayObject):
667 class HTML(TextDisplayObject):
668
668
669 def _repr_html_(self):
669 def _repr_html_(self):
670 return self._data_and_metadata()
670 return self._data_and_metadata()
671
671
672 def __html__(self):
672 def __html__(self):
673 """
673 """
674 This method exists to inform other HTML-using modules (e.g. Markupsafe,
674 This method exists to inform other HTML-using modules (e.g. Markupsafe,
675 htmltag, etc) that this object is HTML and does not need things like
675 htmltag, etc) that this object is HTML and does not need things like
676 special characters (<>&) escaped.
676 special characters (<>&) escaped.
677 """
677 """
678 return self._repr_html_()
678 return self._repr_html_()
679
679
680
680
681 class Markdown(TextDisplayObject):
681 class Markdown(TextDisplayObject):
682
682
683 def _repr_markdown_(self):
683 def _repr_markdown_(self):
684 return self._data_and_metadata()
684 return self._data_and_metadata()
685
685
686
686
687 class Math(TextDisplayObject):
687 class Math(TextDisplayObject):
688
688
689 def _repr_latex_(self):
689 def _repr_latex_(self):
690 s = "$$%s$$" % self.data.strip('$')
690 s = "$$%s$$" % self.data.strip('$')
691 if self.metadata:
691 if self.metadata:
692 return s, deepcopy(self.metadata)
692 return s, deepcopy(self.metadata)
693 else:
693 else:
694 return s
694 return s
695
695
696
696
697 class Latex(TextDisplayObject):
697 class Latex(TextDisplayObject):
698
698
699 def _repr_latex_(self):
699 def _repr_latex_(self):
700 return self._data_and_metadata()
700 return self._data_and_metadata()
701
701
702
702
703 class SVG(DisplayObject):
703 class SVG(DisplayObject):
704
704
705 _read_flags = 'rb'
705 _read_flags = 'rb'
706 # wrap data in a property, which extracts the <svg> tag, discarding
706 # wrap data in a property, which extracts the <svg> tag, discarding
707 # document headers
707 # document headers
708 _data = None
708 _data = None
709
709
710 @property
710 @property
711 def data(self):
711 def data(self):
712 return self._data
712 return self._data
713
713
714 @data.setter
714 @data.setter
715 def data(self, svg):
715 def data(self, svg):
716 if svg is None:
716 if svg is None:
717 self._data = None
717 self._data = None
718 return
718 return
719 # parse into dom object
719 # parse into dom object
720 from xml.dom import minidom
720 from xml.dom import minidom
721 x = minidom.parseString(svg)
721 x = minidom.parseString(svg)
722 # get svg tag (should be 1)
722 # get svg tag (should be 1)
723 found_svg = x.getElementsByTagName('svg')
723 found_svg = x.getElementsByTagName('svg')
724 if found_svg:
724 if found_svg:
725 svg = found_svg[0].toxml()
725 svg = found_svg[0].toxml()
726 else:
726 else:
727 # fallback on the input, trust the user
727 # fallback on the input, trust the user
728 # but this is probably an error.
728 # but this is probably an error.
729 pass
729 pass
730 svg = cast_unicode(svg)
730 svg = cast_unicode(svg)
731 self._data = svg
731 self._data = svg
732
732
733 def _repr_svg_(self):
733 def _repr_svg_(self):
734 return self._data_and_metadata()
734 return self._data_and_metadata()
735
735
736 class ProgressBar(DisplayObject):
736 class ProgressBar(DisplayObject):
737 """Progressbar supports displaying a progressbar like element
737 """Progressbar supports displaying a progressbar like element
738 """
738 """
739 def __init__(self, total):
739 def __init__(self, total):
740 """Creates a new progressbar
740 """Creates a new progressbar
741
741
742 Parameters
742 Parameters
743 ----------
743 ----------
744 total : int
744 total : int
745 maximum size of the progressbar
745 maximum size of the progressbar
746 """
746 """
747 self.total = total
747 self.total = total
748 self._progress = 0
748 self._progress = 0
749 self.html_width = '60ex'
749 self.html_width = '60ex'
750 self.text_width = 60
750 self.text_width = 60
751 self._display_id = hexlify(os.urandom(8)).decode('ascii')
751 self._display_id = hexlify(os.urandom(8)).decode('ascii')
752
752
753 def __repr__(self):
753 def __repr__(self):
754 fraction = self.progress / self.total
754 fraction = self.progress / self.total
755 filled = '=' * int(fraction * self.text_width)
755 filled = '=' * int(fraction * self.text_width)
756 rest = ' ' * (self.text_width - len(filled))
756 rest = ' ' * (self.text_width - len(filled))
757 return '[{}{}] {}/{}'.format(
757 return '[{}{}] {}/{}'.format(
758 filled, rest,
758 filled, rest,
759 self.progress, self.total,
759 self.progress, self.total,
760 )
760 )
761
761
762 def _repr_html_(self):
762 def _repr_html_(self):
763 return "<progress style='width:{}' max='{}' value='{}'></progress>".format(
763 return "<progress style='width:{}' max='{}' value='{}'></progress>".format(
764 self.html_width, self.total, self.progress)
764 self.html_width, self.total, self.progress)
765
765
766 def display(self):
766 def display(self):
767 display(self, display_id=self._display_id)
767 display(self, display_id=self._display_id)
768
768
769 def update(self):
769 def update(self):
770 display(self, display_id=self._display_id, update=True)
770 display(self, display_id=self._display_id, update=True)
771
771
772 @property
772 @property
773 def progress(self):
773 def progress(self):
774 return self._progress
774 return self._progress
775
775
776 @progress.setter
776 @progress.setter
777 def progress(self, value):
777 def progress(self, value):
778 self._progress = value
778 self._progress = value
779 self.update()
779 self.update()
780
780
781 def __iter__(self):
781 def __iter__(self):
782 self.display()
782 self.display()
783 self._progress = -1 # First iteration is 0
783 self._progress = -1 # First iteration is 0
784 return self
784 return self
785
785
786 def __next__(self):
786 def __next__(self):
787 """Returns current value and increments display by one."""
787 """Returns current value and increments display by one."""
788 self.progress += 1
788 self.progress += 1
789 if self.progress < self.total:
789 if self.progress < self.total:
790 return self.progress
790 return self.progress
791 else:
791 else:
792 raise StopIteration()
792 raise StopIteration()
793
793
794 class JSON(DisplayObject):
794 class JSON(DisplayObject):
795 """JSON expects a JSON-able dict or list
795 """JSON expects a JSON-able dict or list
796
796
797 not an already-serialized JSON string.
797 not an already-serialized JSON string.
798
798
799 Scalar types (None, number, string) are not allowed, only dict or list containers.
799 Scalar types (None, number, string) are not allowed, only dict or list containers.
800 """
800 """
801 # wrap data in a property, which warns about passing already-serialized JSON
801 # wrap data in a property, which warns about passing already-serialized JSON
802 _data = None
802 _data = None
803 def __init__(self, data=None, url=None, filename=None, expanded=False, metadata=None, **kwargs):
803 def __init__(self, data=None, url=None, filename=None, expanded=False, metadata=None, root='root', **kwargs):
804 """Create a JSON display object given raw data.
804 """Create a JSON display object given raw data.
805
805
806 Parameters
806 Parameters
807 ----------
807 ----------
808 data : dict or list
808 data : dict or list
809 JSON data to display. Not an already-serialized JSON string.
809 JSON data to display. Not an already-serialized JSON string.
810 Scalar types (None, number, string) are not allowed, only dict
810 Scalar types (None, number, string) are not allowed, only dict
811 or list containers.
811 or list containers.
812 url : unicode
812 url : unicode
813 A URL to download the data from.
813 A URL to download the data from.
814 filename : unicode
814 filename : unicode
815 Path to a local file to load the data from.
815 Path to a local file to load the data from.
816 expanded : boolean
816 expanded : boolean
817 Metadata to control whether a JSON display component is expanded.
817 Metadata to control whether a JSON display component is expanded.
818 metadata: dict
818 metadata: dict
819 Specify extra metadata to attach to the json display object.
819 Specify extra metadata to attach to the json display object.
820 root : str
821 The name of the root element of the JSON tree
820 """
822 """
821 self.metadata = {'expanded': expanded}
823 self.metadata = {
824 'expanded': expanded,
825 'root': root,
826 }
822 if metadata:
827 if metadata:
823 self.metadata.update(metadata)
828 self.metadata.update(metadata)
824 if kwargs:
829 if kwargs:
825 self.metadata.update(kwargs)
830 self.metadata.update(kwargs)
826 super(JSON, self).__init__(data=data, url=url, filename=filename)
831 super(JSON, self).__init__(data=data, url=url, filename=filename)
827
832
828 def _check_data(self):
833 def _check_data(self):
829 if self.data is not None and not isinstance(self.data, (dict, list)):
834 if self.data is not None and not isinstance(self.data, (dict, list)):
830 raise TypeError("%s expects JSONable dict or list, not %r" % (self.__class__.__name__, self.data))
835 raise TypeError("%s expects JSONable dict or list, not %r" % (self.__class__.__name__, self.data))
831
836
832 @property
837 @property
833 def data(self):
838 def data(self):
834 return self._data
839 return self._data
835
840
836 @data.setter
841 @data.setter
837 def data(self, data):
842 def data(self, data):
838 if isinstance(data, str):
843 if isinstance(data, str):
839 if getattr(self, 'filename', None) is None:
844 if getattr(self, 'filename', None) is None:
840 warnings.warn("JSON expects JSONable dict or list, not JSON strings")
845 warnings.warn("JSON expects JSONable dict or list, not JSON strings")
841 data = json.loads(data)
846 data = json.loads(data)
842 self._data = data
847 self._data = data
843
848
844 def _data_and_metadata(self):
849 def _data_and_metadata(self):
845 return self.data, self.metadata
850 return self.data, self.metadata
846
851
847 def _repr_json_(self):
852 def _repr_json_(self):
848 return self._data_and_metadata()
853 return self._data_and_metadata()
849
854
850 _css_t = """$("head").append($("<link/>").attr({
855 _css_t = """var link = document.createElement("link");
851 rel: "stylesheet",
856 link.ref = "stylesheet";
852 type: "text/css",
857 link.type = "text/css";
853 href: "%s"
858 link.href = "%s";
854 }));
859 document.head.appendChild(link);
855 """
860 """
856
861
857 _lib_t1 = """$.getScript("%s", function () {
862 _lib_t1 = """new Promise(function(resolve, reject) {
858 """
863 var script = document.createElement("script");
859 _lib_t2 = """});
864 script.onload = resolve;
865 script.onerror = reject;
866 script.src = "%s";
867 document.head.appendChild(script);
868 }).then(() => {
860 """
869 """
861
870
871 _lib_t2 = """
872 });"""
873
862 class GeoJSON(JSON):
874 class GeoJSON(JSON):
863 """GeoJSON expects JSON-able dict
875 """GeoJSON expects JSON-able dict
864
876
865 not an already-serialized JSON string.
877 not an already-serialized JSON string.
866
878
867 Scalar types (None, number, string) are not allowed, only dict containers.
879 Scalar types (None, number, string) are not allowed, only dict containers.
868 """
880 """
869
881
870 def __init__(self, *args, **kwargs):
882 def __init__(self, *args, **kwargs):
871 """Create a GeoJSON display object given raw data.
883 """Create a GeoJSON display object given raw data.
872
884
873 Parameters
885 Parameters
874 ----------
886 ----------
875 data : dict or list
887 data : dict or list
876 VegaLite data. Not an already-serialized JSON string.
888 VegaLite data. Not an already-serialized JSON string.
877 Scalar types (None, number, string) are not allowed, only dict
889 Scalar types (None, number, string) are not allowed, only dict
878 or list containers.
890 or list containers.
879 url_template : string
891 url_template : string
880 Leaflet TileLayer URL template: http://leafletjs.com/reference.html#url-template
892 Leaflet TileLayer URL template: http://leafletjs.com/reference.html#url-template
881 layer_options : dict
893 layer_options : dict
882 Leaflet TileLayer options: http://leafletjs.com/reference.html#tilelayer-options
894 Leaflet TileLayer options: http://leafletjs.com/reference.html#tilelayer-options
883 url : unicode
895 url : unicode
884 A URL to download the data from.
896 A URL to download the data from.
885 filename : unicode
897 filename : unicode
886 Path to a local file to load the data from.
898 Path to a local file to load the data from.
887 metadata: dict
899 metadata: dict
888 Specify extra metadata to attach to the json display object.
900 Specify extra metadata to attach to the json display object.
889
901
890 Examples
902 Examples
891 --------
903 --------
892
904
893 The following will display an interactive map of Mars with a point of
905 The following will display an interactive map of Mars with a point of
894 interest on frontend that do support GeoJSON display.
906 interest on frontend that do support GeoJSON display.
895
907
896 >>> from IPython.display import GeoJSON
908 >>> from IPython.display import GeoJSON
897
909
898 >>> GeoJSON(data={
910 >>> GeoJSON(data={
899 ... "type": "Feature",
911 ... "type": "Feature",
900 ... "geometry": {
912 ... "geometry": {
901 ... "type": "Point",
913 ... "type": "Point",
902 ... "coordinates": [-81.327, 296.038]
914 ... "coordinates": [-81.327, 296.038]
903 ... }
915 ... }
904 ... },
916 ... },
905 ... url_template="http://s3-eu-west-1.amazonaws.com/whereonmars.cartodb.net/{basemap_id}/{z}/{x}/{y}.png",
917 ... url_template="http://s3-eu-west-1.amazonaws.com/whereonmars.cartodb.net/{basemap_id}/{z}/{x}/{y}.png",
906 ... layer_options={
918 ... layer_options={
907 ... "basemap_id": "celestia_mars-shaded-16k_global",
919 ... "basemap_id": "celestia_mars-shaded-16k_global",
908 ... "attribution" : "Celestia/praesepe",
920 ... "attribution" : "Celestia/praesepe",
909 ... "minZoom" : 0,
921 ... "minZoom" : 0,
910 ... "maxZoom" : 18,
922 ... "maxZoom" : 18,
911 ... })
923 ... })
912 <IPython.core.display.GeoJSON object>
924 <IPython.core.display.GeoJSON object>
913
925
914 In the terminal IPython, you will only see the text representation of
926 In the terminal IPython, you will only see the text representation of
915 the GeoJSON object.
927 the GeoJSON object.
916
928
917 """
929 """
918
930
919 super(GeoJSON, self).__init__(*args, **kwargs)
931 super(GeoJSON, self).__init__(*args, **kwargs)
920
932
921
933
922 def _ipython_display_(self):
934 def _ipython_display_(self):
923 bundle = {
935 bundle = {
924 'application/geo+json': self.data,
936 'application/geo+json': self.data,
925 'text/plain': '<IPython.display.GeoJSON object>'
937 'text/plain': '<IPython.display.GeoJSON object>'
926 }
938 }
927 metadata = {
939 metadata = {
928 'application/geo+json': self.metadata
940 'application/geo+json': self.metadata
929 }
941 }
930 display(bundle, metadata=metadata, raw=True)
942 display(bundle, metadata=metadata, raw=True)
931
943
932 class Javascript(TextDisplayObject):
944 class Javascript(TextDisplayObject):
933
945
934 def __init__(self, data=None, url=None, filename=None, lib=None, css=None):
946 def __init__(self, data=None, url=None, filename=None, lib=None, css=None):
935 """Create a Javascript display object given raw data.
947 """Create a Javascript display object given raw data.
936
948
937 When this object is returned by an expression or passed to the
949 When this object is returned by an expression or passed to the
938 display function, it will result in the data being displayed
950 display function, it will result in the data being displayed
939 in the frontend. If the data is a URL, the data will first be
951 in the frontend. If the data is a URL, the data will first be
940 downloaded and then displayed.
952 downloaded and then displayed.
941
953
942 In the Notebook, the containing element will be available as `element`,
954 In the Notebook, the containing element will be available as `element`,
943 and jQuery will be available. Content appended to `element` will be
955 and jQuery will be available. Content appended to `element` will be
944 visible in the output area.
956 visible in the output area.
945
957
946 Parameters
958 Parameters
947 ----------
959 ----------
948 data : unicode, str or bytes
960 data : unicode, str or bytes
949 The Javascript source code or a URL to download it from.
961 The Javascript source code or a URL to download it from.
950 url : unicode
962 url : unicode
951 A URL to download the data from.
963 A URL to download the data from.
952 filename : unicode
964 filename : unicode
953 Path to a local file to load the data from.
965 Path to a local file to load the data from.
954 lib : list or str
966 lib : list or str
955 A sequence of Javascript library URLs to load asynchronously before
967 A sequence of Javascript library URLs to load asynchronously before
956 running the source code. The full URLs of the libraries should
968 running the source code. The full URLs of the libraries should
957 be given. A single Javascript library URL can also be given as a
969 be given. A single Javascript library URL can also be given as a
958 string.
970 string.
959 css: : list or str
971 css: : list or str
960 A sequence of css files to load before running the source code.
972 A sequence of css files to load before running the source code.
961 The full URLs of the css files should be given. A single css URL
973 The full URLs of the css files should be given. A single css URL
962 can also be given as a string.
974 can also be given as a string.
963 """
975 """
964 if isinstance(lib, str):
976 if isinstance(lib, str):
965 lib = [lib]
977 lib = [lib]
966 elif lib is None:
978 elif lib is None:
967 lib = []
979 lib = []
968 if isinstance(css, str):
980 if isinstance(css, str):
969 css = [css]
981 css = [css]
970 elif css is None:
982 elif css is None:
971 css = []
983 css = []
972 if not isinstance(lib, (list,tuple)):
984 if not isinstance(lib, (list,tuple)):
973 raise TypeError('expected sequence, got: %r' % lib)
985 raise TypeError('expected sequence, got: %r' % lib)
974 if not isinstance(css, (list,tuple)):
986 if not isinstance(css, (list,tuple)):
975 raise TypeError('expected sequence, got: %r' % css)
987 raise TypeError('expected sequence, got: %r' % css)
976 self.lib = lib
988 self.lib = lib
977 self.css = css
989 self.css = css
978 super(Javascript, self).__init__(data=data, url=url, filename=filename)
990 super(Javascript, self).__init__(data=data, url=url, filename=filename)
979
991
980 def _repr_javascript_(self):
992 def _repr_javascript_(self):
981 r = ''
993 r = ''
982 for c in self.css:
994 for c in self.css:
983 r += _css_t % c
995 r += _css_t % c
984 for l in self.lib:
996 for l in self.lib:
985 r += _lib_t1 % l
997 r += _lib_t1 % l
986 r += self.data
998 r += self.data
987 r += _lib_t2*len(self.lib)
999 r += _lib_t2*len(self.lib)
988 return r
1000 return r
989
1001
990 # constants for identifying png/jpeg data
1002 # constants for identifying png/jpeg data
991 _PNG = b'\x89PNG\r\n\x1a\n'
1003 _PNG = b'\x89PNG\r\n\x1a\n'
992 _JPEG = b'\xff\xd8'
1004 _JPEG = b'\xff\xd8'
993
1005
994 def _pngxy(data):
1006 def _pngxy(data):
995 """read the (width, height) from a PNG header"""
1007 """read the (width, height) from a PNG header"""
996 ihdr = data.index(b'IHDR')
1008 ihdr = data.index(b'IHDR')
997 # next 8 bytes are width/height
1009 # next 8 bytes are width/height
998 return struct.unpack('>ii', data[ihdr+4:ihdr+12])
1010 return struct.unpack('>ii', data[ihdr+4:ihdr+12])
999
1011
1000 def _jpegxy(data):
1012 def _jpegxy(data):
1001 """read the (width, height) from a JPEG header"""
1013 """read the (width, height) from a JPEG header"""
1002 # adapted from http://www.64lines.com/jpeg-width-height
1014 # adapted from http://www.64lines.com/jpeg-width-height
1003
1015
1004 idx = 4
1016 idx = 4
1005 while True:
1017 while True:
1006 block_size = struct.unpack('>H', data[idx:idx+2])[0]
1018 block_size = struct.unpack('>H', data[idx:idx+2])[0]
1007 idx = idx + block_size
1019 idx = idx + block_size
1008 if data[idx:idx+2] == b'\xFF\xC0':
1020 if data[idx:idx+2] == b'\xFF\xC0':
1009 # found Start of Frame
1021 # found Start of Frame
1010 iSOF = idx
1022 iSOF = idx
1011 break
1023 break
1012 else:
1024 else:
1013 # read another block
1025 # read another block
1014 idx += 2
1026 idx += 2
1015
1027
1016 h, w = struct.unpack('>HH', data[iSOF+5:iSOF+9])
1028 h, w = struct.unpack('>HH', data[iSOF+5:iSOF+9])
1017 return w, h
1029 return w, h
1018
1030
1019 def _gifxy(data):
1031 def _gifxy(data):
1020 """read the (width, height) from a GIF header"""
1032 """read the (width, height) from a GIF header"""
1021 return struct.unpack('<HH', data[6:10])
1033 return struct.unpack('<HH', data[6:10])
1022
1034
1023
1035
1024 class Image(DisplayObject):
1036 class Image(DisplayObject):
1025
1037
1026 _read_flags = 'rb'
1038 _read_flags = 'rb'
1027 _FMT_JPEG = u'jpeg'
1039 _FMT_JPEG = u'jpeg'
1028 _FMT_PNG = u'png'
1040 _FMT_PNG = u'png'
1029 _FMT_GIF = u'gif'
1041 _FMT_GIF = u'gif'
1030 _ACCEPTABLE_EMBEDDINGS = [_FMT_JPEG, _FMT_PNG, _FMT_GIF]
1042 _ACCEPTABLE_EMBEDDINGS = [_FMT_JPEG, _FMT_PNG, _FMT_GIF]
1031 _MIMETYPES = {
1043 _MIMETYPES = {
1032 _FMT_PNG: 'image/png',
1044 _FMT_PNG: 'image/png',
1033 _FMT_JPEG: 'image/jpeg',
1045 _FMT_JPEG: 'image/jpeg',
1034 _FMT_GIF: 'image/gif',
1046 _FMT_GIF: 'image/gif',
1035 }
1047 }
1036
1048
1037 def __init__(self, data=None, url=None, filename=None, format=None,
1049 def __init__(self, data=None, url=None, filename=None, format=None,
1038 embed=None, width=None, height=None, retina=False,
1050 embed=None, width=None, height=None, retina=False,
1039 unconfined=False, metadata=None):
1051 unconfined=False, metadata=None):
1040 """Create a PNG/JPEG/GIF image object given raw data.
1052 """Create a PNG/JPEG/GIF image object given raw data.
1041
1053
1042 When this object is returned by an input cell or passed to the
1054 When this object is returned by an input cell or passed to the
1043 display function, it will result in the image being displayed
1055 display function, it will result in the image being displayed
1044 in the frontend.
1056 in the frontend.
1045
1057
1046 Parameters
1058 Parameters
1047 ----------
1059 ----------
1048 data : unicode, str or bytes
1060 data : unicode, str or bytes
1049 The raw image data or a URL or filename to load the data from.
1061 The raw image data or a URL or filename to load the data from.
1050 This always results in embedded image data.
1062 This always results in embedded image data.
1051 url : unicode
1063 url : unicode
1052 A URL to download the data from. If you specify `url=`,
1064 A URL to download the data from. If you specify `url=`,
1053 the image data will not be embedded unless you also specify `embed=True`.
1065 the image data will not be embedded unless you also specify `embed=True`.
1054 filename : unicode
1066 filename : unicode
1055 Path to a local file to load the data from.
1067 Path to a local file to load the data from.
1056 Images from a file are always embedded.
1068 Images from a file are always embedded.
1057 format : unicode
1069 format : unicode
1058 The format of the image data (png/jpeg/jpg/gif). If a filename or URL is given
1070 The format of the image data (png/jpeg/jpg/gif). If a filename or URL is given
1059 for format will be inferred from the filename extension.
1071 for format will be inferred from the filename extension.
1060 embed : bool
1072 embed : bool
1061 Should the image data be embedded using a data URI (True) or be
1073 Should the image data be embedded using a data URI (True) or be
1062 loaded using an <img> tag. Set this to True if you want the image
1074 loaded using an <img> tag. Set this to True if you want the image
1063 to be viewable later with no internet connection in the notebook.
1075 to be viewable later with no internet connection in the notebook.
1064
1076
1065 Default is `True`, unless the keyword argument `url` is set, then
1077 Default is `True`, unless the keyword argument `url` is set, then
1066 default value is `False`.
1078 default value is `False`.
1067
1079
1068 Note that QtConsole is not able to display images if `embed` is set to `False`
1080 Note that QtConsole is not able to display images if `embed` is set to `False`
1069 width : int
1081 width : int
1070 Width in pixels to which to constrain the image in html
1082 Width in pixels to which to constrain the image in html
1071 height : int
1083 height : int
1072 Height in pixels to which to constrain the image in html
1084 Height in pixels to which to constrain the image in html
1073 retina : bool
1085 retina : bool
1074 Automatically set the width and height to half of the measured
1086 Automatically set the width and height to half of the measured
1075 width and height.
1087 width and height.
1076 This only works for embedded images because it reads the width/height
1088 This only works for embedded images because it reads the width/height
1077 from image data.
1089 from image data.
1078 For non-embedded images, you can just set the desired display width
1090 For non-embedded images, you can just set the desired display width
1079 and height directly.
1091 and height directly.
1080 unconfined: bool
1092 unconfined: bool
1081 Set unconfined=True to disable max-width confinement of the image.
1093 Set unconfined=True to disable max-width confinement of the image.
1082 metadata: dict
1094 metadata: dict
1083 Specify extra metadata to attach to the image.
1095 Specify extra metadata to attach to the image.
1084
1096
1085 Examples
1097 Examples
1086 --------
1098 --------
1087 # embedded image data, works in qtconsole and notebook
1099 # embedded image data, works in qtconsole and notebook
1088 # when passed positionally, the first arg can be any of raw image data,
1100 # when passed positionally, the first arg can be any of raw image data,
1089 # a URL, or a filename from which to load image data.
1101 # a URL, or a filename from which to load image data.
1090 # The result is always embedding image data for inline images.
1102 # The result is always embedding image data for inline images.
1091 Image('http://www.google.fr/images/srpr/logo3w.png')
1103 Image('http://www.google.fr/images/srpr/logo3w.png')
1092 Image('/path/to/image.jpg')
1104 Image('/path/to/image.jpg')
1093 Image(b'RAW_PNG_DATA...')
1105 Image(b'RAW_PNG_DATA...')
1094
1106
1095 # Specifying Image(url=...) does not embed the image data,
1107 # Specifying Image(url=...) does not embed the image data,
1096 # it only generates `<img>` tag with a link to the source.
1108 # it only generates `<img>` tag with a link to the source.
1097 # This will not work in the qtconsole or offline.
1109 # This will not work in the qtconsole or offline.
1098 Image(url='http://www.google.fr/images/srpr/logo3w.png')
1110 Image(url='http://www.google.fr/images/srpr/logo3w.png')
1099
1111
1100 """
1112 """
1101 if filename is not None:
1113 if filename is not None:
1102 ext = self._find_ext(filename)
1114 ext = self._find_ext(filename)
1103 elif url is not None:
1115 elif url is not None:
1104 ext = self._find_ext(url)
1116 ext = self._find_ext(url)
1105 elif data is None:
1117 elif data is None:
1106 raise ValueError("No image data found. Expecting filename, url, or data.")
1118 raise ValueError("No image data found. Expecting filename, url, or data.")
1107 elif isinstance(data, str) and (
1119 elif isinstance(data, str) and (
1108 data.startswith('http') or _safe_exists(data)
1120 data.startswith('http') or _safe_exists(data)
1109 ):
1121 ):
1110 ext = self._find_ext(data)
1122 ext = self._find_ext(data)
1111 else:
1123 else:
1112 ext = None
1124 ext = None
1113
1125
1114 if format is None:
1126 if format is None:
1115 if ext is not None:
1127 if ext is not None:
1116 if ext == u'jpg' or ext == u'jpeg':
1128 if ext == u'jpg' or ext == u'jpeg':
1117 format = self._FMT_JPEG
1129 format = self._FMT_JPEG
1118 elif ext == u'png':
1130 elif ext == u'png':
1119 format = self._FMT_PNG
1131 format = self._FMT_PNG
1120 elif ext == u'gif':
1132 elif ext == u'gif':
1121 format = self._FMT_GIF
1133 format = self._FMT_GIF
1122 else:
1134 else:
1123 format = ext.lower()
1135 format = ext.lower()
1124 elif isinstance(data, bytes):
1136 elif isinstance(data, bytes):
1125 # infer image type from image data header,
1137 # infer image type from image data header,
1126 # only if format has not been specified.
1138 # only if format has not been specified.
1127 if data[:2] == _JPEG:
1139 if data[:2] == _JPEG:
1128 format = self._FMT_JPEG
1140 format = self._FMT_JPEG
1129
1141
1130 # failed to detect format, default png
1142 # failed to detect format, default png
1131 if format is None:
1143 if format is None:
1132 format = self._FMT_PNG
1144 format = self._FMT_PNG
1133
1145
1134 if format.lower() == 'jpg':
1146 if format.lower() == 'jpg':
1135 # jpg->jpeg
1147 # jpg->jpeg
1136 format = self._FMT_JPEG
1148 format = self._FMT_JPEG
1137
1149
1138 self.format = format.lower()
1150 self.format = format.lower()
1139 self.embed = embed if embed is not None else (url is None)
1151 self.embed = embed if embed is not None else (url is None)
1140
1152
1141 if self.embed and self.format not in self._ACCEPTABLE_EMBEDDINGS:
1153 if self.embed and self.format not in self._ACCEPTABLE_EMBEDDINGS:
1142 raise ValueError("Cannot embed the '%s' image format" % (self.format))
1154 raise ValueError("Cannot embed the '%s' image format" % (self.format))
1143 if self.embed:
1155 if self.embed:
1144 self._mimetype = self._MIMETYPES.get(self.format)
1156 self._mimetype = self._MIMETYPES.get(self.format)
1145
1157
1146 self.width = width
1158 self.width = width
1147 self.height = height
1159 self.height = height
1148 self.retina = retina
1160 self.retina = retina
1149 self.unconfined = unconfined
1161 self.unconfined = unconfined
1150 super(Image, self).__init__(data=data, url=url, filename=filename,
1162 super(Image, self).__init__(data=data, url=url, filename=filename,
1151 metadata=metadata)
1163 metadata=metadata)
1152
1164
1153 if self.width is None and self.metadata.get('width', {}):
1165 if self.width is None and self.metadata.get('width', {}):
1154 self.width = metadata['width']
1166 self.width = metadata['width']
1155
1167
1156 if self.height is None and self.metadata.get('height', {}):
1168 if self.height is None and self.metadata.get('height', {}):
1157 self.height = metadata['height']
1169 self.height = metadata['height']
1158
1170
1159 if retina:
1171 if retina:
1160 self._retina_shape()
1172 self._retina_shape()
1161
1173
1162
1174
1163 def _retina_shape(self):
1175 def _retina_shape(self):
1164 """load pixel-doubled width and height from image data"""
1176 """load pixel-doubled width and height from image data"""
1165 if not self.embed:
1177 if not self.embed:
1166 return
1178 return
1167 if self.format == self._FMT_PNG:
1179 if self.format == self._FMT_PNG:
1168 w, h = _pngxy(self.data)
1180 w, h = _pngxy(self.data)
1169 elif self.format == self._FMT_JPEG:
1181 elif self.format == self._FMT_JPEG:
1170 w, h = _jpegxy(self.data)
1182 w, h = _jpegxy(self.data)
1171 elif self.format == self._FMT_GIF:
1183 elif self.format == self._FMT_GIF:
1172 w, h = _gifxy(self.data)
1184 w, h = _gifxy(self.data)
1173 else:
1185 else:
1174 # retina only supports png
1186 # retina only supports png
1175 return
1187 return
1176 self.width = w // 2
1188 self.width = w // 2
1177 self.height = h // 2
1189 self.height = h // 2
1178
1190
1179 def reload(self):
1191 def reload(self):
1180 """Reload the raw data from file or URL."""
1192 """Reload the raw data from file or URL."""
1181 if self.embed:
1193 if self.embed:
1182 super(Image,self).reload()
1194 super(Image,self).reload()
1183 if self.retina:
1195 if self.retina:
1184 self._retina_shape()
1196 self._retina_shape()
1185
1197
1186 def _repr_html_(self):
1198 def _repr_html_(self):
1187 if not self.embed:
1199 if not self.embed:
1188 width = height = klass = ''
1200 width = height = klass = ''
1189 if self.width:
1201 if self.width:
1190 width = ' width="%d"' % self.width
1202 width = ' width="%d"' % self.width
1191 if self.height:
1203 if self.height:
1192 height = ' height="%d"' % self.height
1204 height = ' height="%d"' % self.height
1193 if self.unconfined:
1205 if self.unconfined:
1194 klass = ' class="unconfined"'
1206 klass = ' class="unconfined"'
1195 return u'<img src="{url}"{width}{height}{klass}/>'.format(
1207 return u'<img src="{url}"{width}{height}{klass}/>'.format(
1196 url=self.url,
1208 url=self.url,
1197 width=width,
1209 width=width,
1198 height=height,
1210 height=height,
1199 klass=klass,
1211 klass=klass,
1200 )
1212 )
1201
1213
1202 def _repr_mimebundle_(self, include=None, exclude=None):
1214 def _repr_mimebundle_(self, include=None, exclude=None):
1203 """Return the image as a mimebundle
1215 """Return the image as a mimebundle
1204
1216
1205 Any new mimetype support should be implemented here.
1217 Any new mimetype support should be implemented here.
1206 """
1218 """
1207 if self.embed:
1219 if self.embed:
1208 mimetype = self._mimetype
1220 mimetype = self._mimetype
1209 data, metadata = self._data_and_metadata(always_both=True)
1221 data, metadata = self._data_and_metadata(always_both=True)
1210 if metadata:
1222 if metadata:
1211 metadata = {mimetype: metadata}
1223 metadata = {mimetype: metadata}
1212 return {mimetype: data}, metadata
1224 return {mimetype: data}, metadata
1213 else:
1225 else:
1214 return {'text/html': self._repr_html_()}
1226 return {'text/html': self._repr_html_()}
1215
1227
1216 def _data_and_metadata(self, always_both=False):
1228 def _data_and_metadata(self, always_both=False):
1217 """shortcut for returning metadata with shape information, if defined"""
1229 """shortcut for returning metadata with shape information, if defined"""
1218 b64_data = b2a_base64(self.data).decode('ascii')
1230 b64_data = b2a_base64(self.data).decode('ascii')
1219 md = {}
1231 md = {}
1220 if self.metadata:
1232 if self.metadata:
1221 md.update(self.metadata)
1233 md.update(self.metadata)
1222 if self.width:
1234 if self.width:
1223 md['width'] = self.width
1235 md['width'] = self.width
1224 if self.height:
1236 if self.height:
1225 md['height'] = self.height
1237 md['height'] = self.height
1226 if self.unconfined:
1238 if self.unconfined:
1227 md['unconfined'] = self.unconfined
1239 md['unconfined'] = self.unconfined
1228 if md or always_both:
1240 if md or always_both:
1229 return b64_data, md
1241 return b64_data, md
1230 else:
1242 else:
1231 return b64_data
1243 return b64_data
1232
1244
1233 def _repr_png_(self):
1245 def _repr_png_(self):
1234 if self.embed and self.format == self._FMT_PNG:
1246 if self.embed and self.format == self._FMT_PNG:
1235 return self._data_and_metadata()
1247 return self._data_and_metadata()
1236
1248
1237 def _repr_jpeg_(self):
1249 def _repr_jpeg_(self):
1238 if self.embed and self.format == self._FMT_JPEG:
1250 if self.embed and self.format == self._FMT_JPEG:
1239 return self._data_and_metadata()
1251 return self._data_and_metadata()
1240
1252
1241 def _find_ext(self, s):
1253 def _find_ext(self, s):
1242 return s.split('.')[-1].lower()
1254 return s.split('.')[-1].lower()
1243
1255
1244
1256
1245 class Video(DisplayObject):
1257 class Video(DisplayObject):
1246
1258
1247 def __init__(self, data=None, url=None, filename=None, embed=False, mimetype=None):
1259 def __init__(self, data=None, url=None, filename=None, embed=False, mimetype=None):
1248 """Create a video object given raw data or an URL.
1260 """Create a video object given raw data or an URL.
1249
1261
1250 When this object is returned by an input cell or passed to the
1262 When this object is returned by an input cell or passed to the
1251 display function, it will result in the video being displayed
1263 display function, it will result in the video being displayed
1252 in the frontend.
1264 in the frontend.
1253
1265
1254 Parameters
1266 Parameters
1255 ----------
1267 ----------
1256 data : unicode, str or bytes
1268 data : unicode, str or bytes
1257 The raw video data or a URL or filename to load the data from.
1269 The raw video data or a URL or filename to load the data from.
1258 Raw data will require passing `embed=True`.
1270 Raw data will require passing `embed=True`.
1259 url : unicode
1271 url : unicode
1260 A URL for the video. If you specify `url=`,
1272 A URL for the video. If you specify `url=`,
1261 the image data will not be embedded.
1273 the image data will not be embedded.
1262 filename : unicode
1274 filename : unicode
1263 Path to a local file containing the video.
1275 Path to a local file containing the video.
1264 Will be interpreted as a local URL unless `embed=True`.
1276 Will be interpreted as a local URL unless `embed=True`.
1265 embed : bool
1277 embed : bool
1266 Should the video be embedded using a data URI (True) or be
1278 Should the video be embedded using a data URI (True) or be
1267 loaded using a <video> tag (False).
1279 loaded using a <video> tag (False).
1268
1280
1269 Since videos are large, embedding them should be avoided, if possible.
1281 Since videos are large, embedding them should be avoided, if possible.
1270 You must confirm embedding as your intention by passing `embed=True`.
1282 You must confirm embedding as your intention by passing `embed=True`.
1271
1283
1272 Local files can be displayed with URLs without embedding the content, via::
1284 Local files can be displayed with URLs without embedding the content, via::
1273
1285
1274 Video('./video.mp4')
1286 Video('./video.mp4')
1275
1287
1276 mimetype: unicode
1288 mimetype: unicode
1277 Specify the mimetype for embedded videos.
1289 Specify the mimetype for embedded videos.
1278 Default will be guessed from file extension, if available.
1290 Default will be guessed from file extension, if available.
1279
1291
1280 Examples
1292 Examples
1281 --------
1293 --------
1282
1294
1283 Video('https://archive.org/download/Sita_Sings_the_Blues/Sita_Sings_the_Blues_small.mp4')
1295 Video('https://archive.org/download/Sita_Sings_the_Blues/Sita_Sings_the_Blues_small.mp4')
1284 Video('path/to/video.mp4')
1296 Video('path/to/video.mp4')
1285 Video('path/to/video.mp4', embed=True)
1297 Video('path/to/video.mp4', embed=True)
1286 Video(b'raw-videodata', embed=True)
1298 Video(b'raw-videodata', embed=True)
1287 """
1299 """
1288 if url is None and isinstance(data, str) and data.startswith(('http:', 'https:')):
1300 if url is None and isinstance(data, str) and data.startswith(('http:', 'https:')):
1289 url = data
1301 url = data
1290 data = None
1302 data = None
1291 elif os.path.exists(data):
1303 elif os.path.exists(data):
1292 filename = data
1304 filename = data
1293 data = None
1305 data = None
1294
1306
1295 if data and not embed:
1307 if data and not embed:
1296 msg = ''.join([
1308 msg = ''.join([
1297 "To embed videos, you must pass embed=True ",
1309 "To embed videos, you must pass embed=True ",
1298 "(this may make your notebook files huge)\n",
1310 "(this may make your notebook files huge)\n",
1299 "Consider passing Video(url='...')",
1311 "Consider passing Video(url='...')",
1300 ])
1312 ])
1301 raise ValueError(msg)
1313 raise ValueError(msg)
1302
1314
1303 self.mimetype = mimetype
1315 self.mimetype = mimetype
1304 self.embed = embed
1316 self.embed = embed
1305 super(Video, self).__init__(data=data, url=url, filename=filename)
1317 super(Video, self).__init__(data=data, url=url, filename=filename)
1306
1318
1307 def _repr_html_(self):
1319 def _repr_html_(self):
1308 # External URLs and potentially local files are not embedded into the
1320 # External URLs and potentially local files are not embedded into the
1309 # notebook output.
1321 # notebook output.
1310 if not self.embed:
1322 if not self.embed:
1311 url = self.url if self.url is not None else self.filename
1323 url = self.url if self.url is not None else self.filename
1312 output = """<video src="{0}" controls>
1324 output = """<video src="{0}" controls>
1313 Your browser does not support the <code>video</code> element.
1325 Your browser does not support the <code>video</code> element.
1314 </video>""".format(url)
1326 </video>""".format(url)
1315 return output
1327 return output
1316
1328
1317 # Embedded videos are base64-encoded.
1329 # Embedded videos are base64-encoded.
1318 mimetype = self.mimetype
1330 mimetype = self.mimetype
1319 if self.filename is not None:
1331 if self.filename is not None:
1320 if not mimetype:
1332 if not mimetype:
1321 mimetype, _ = mimetypes.guess_type(self.filename)
1333 mimetype, _ = mimetypes.guess_type(self.filename)
1322
1334
1323 with open(self.filename, 'rb') as f:
1335 with open(self.filename, 'rb') as f:
1324 video = f.read()
1336 video = f.read()
1325 else:
1337 else:
1326 video = self.data
1338 video = self.data
1327 if isinstance(video, str):
1339 if isinstance(video, str):
1328 # unicode input is already b64-encoded
1340 # unicode input is already b64-encoded
1329 b64_video = video
1341 b64_video = video
1330 else:
1342 else:
1331 b64_video = b2a_base64(video).decode('ascii').rstrip()
1343 b64_video = b2a_base64(video).decode('ascii').rstrip()
1332
1344
1333 output = """<video controls>
1345 output = """<video controls>
1334 <source src="data:{0};base64,{1}" type="{0}">
1346 <source src="data:{0};base64,{1}" type="{0}">
1335 Your browser does not support the video tag.
1347 Your browser does not support the video tag.
1336 </video>""".format(mimetype, b64_video)
1348 </video>""".format(mimetype, b64_video)
1337 return output
1349 return output
1338
1350
1339 def reload(self):
1351 def reload(self):
1340 # TODO
1352 # TODO
1341 pass
1353 pass
1342
1354
1343
1355
1344 def clear_output(wait=False):
1356 def clear_output(wait=False):
1345 """Clear the output of the current cell receiving output.
1357 """Clear the output of the current cell receiving output.
1346
1358
1347 Parameters
1359 Parameters
1348 ----------
1360 ----------
1349 wait : bool [default: false]
1361 wait : bool [default: false]
1350 Wait to clear the output until new output is available to replace it."""
1362 Wait to clear the output until new output is available to replace it."""
1351 from IPython.core.interactiveshell import InteractiveShell
1363 from IPython.core.interactiveshell import InteractiveShell
1352 if InteractiveShell.initialized():
1364 if InteractiveShell.initialized():
1353 InteractiveShell.instance().display_pub.clear_output(wait)
1365 InteractiveShell.instance().display_pub.clear_output(wait)
1354 else:
1366 else:
1355 print('\033[2K\r', end='')
1367 print('\033[2K\r', end='')
1356 sys.stdout.flush()
1368 sys.stdout.flush()
1357 print('\033[2K\r', end='')
1369 print('\033[2K\r', end='')
1358 sys.stderr.flush()
1370 sys.stderr.flush()
1359
1371
1360
1372
1361 @skip_doctest
1373 @skip_doctest
1362 def set_matplotlib_formats(*formats, **kwargs):
1374 def set_matplotlib_formats(*formats, **kwargs):
1363 """Select figure formats for the inline backend. Optionally pass quality for JPEG.
1375 """Select figure formats for the inline backend. Optionally pass quality for JPEG.
1364
1376
1365 For example, this enables PNG and JPEG output with a JPEG quality of 90%::
1377 For example, this enables PNG and JPEG output with a JPEG quality of 90%::
1366
1378
1367 In [1]: set_matplotlib_formats('png', 'jpeg', quality=90)
1379 In [1]: set_matplotlib_formats('png', 'jpeg', quality=90)
1368
1380
1369 To set this in your config files use the following::
1381 To set this in your config files use the following::
1370
1382
1371 c.InlineBackend.figure_formats = {'png', 'jpeg'}
1383 c.InlineBackend.figure_formats = {'png', 'jpeg'}
1372 c.InlineBackend.print_figure_kwargs.update({'quality' : 90})
1384 c.InlineBackend.print_figure_kwargs.update({'quality' : 90})
1373
1385
1374 Parameters
1386 Parameters
1375 ----------
1387 ----------
1376 *formats : strs
1388 *formats : strs
1377 One or more figure formats to enable: 'png', 'retina', 'jpeg', 'svg', 'pdf'.
1389 One or more figure formats to enable: 'png', 'retina', 'jpeg', 'svg', 'pdf'.
1378 **kwargs :
1390 **kwargs :
1379 Keyword args will be relayed to ``figure.canvas.print_figure``.
1391 Keyword args will be relayed to ``figure.canvas.print_figure``.
1380 """
1392 """
1381 from IPython.core.interactiveshell import InteractiveShell
1393 from IPython.core.interactiveshell import InteractiveShell
1382 from IPython.core.pylabtools import select_figure_formats
1394 from IPython.core.pylabtools import select_figure_formats
1383 # build kwargs, starting with InlineBackend config
1395 # build kwargs, starting with InlineBackend config
1384 kw = {}
1396 kw = {}
1385 from ipykernel.pylab.config import InlineBackend
1397 from ipykernel.pylab.config import InlineBackend
1386 cfg = InlineBackend.instance()
1398 cfg = InlineBackend.instance()
1387 kw.update(cfg.print_figure_kwargs)
1399 kw.update(cfg.print_figure_kwargs)
1388 kw.update(**kwargs)
1400 kw.update(**kwargs)
1389 shell = InteractiveShell.instance()
1401 shell = InteractiveShell.instance()
1390 select_figure_formats(shell, formats, **kw)
1402 select_figure_formats(shell, formats, **kw)
1391
1403
1392 @skip_doctest
1404 @skip_doctest
1393 def set_matplotlib_close(close=True):
1405 def set_matplotlib_close(close=True):
1394 """Set whether the inline backend closes all figures automatically or not.
1406 """Set whether the inline backend closes all figures automatically or not.
1395
1407
1396 By default, the inline backend used in the IPython Notebook will close all
1408 By default, the inline backend used in the IPython Notebook will close all
1397 matplotlib figures automatically after each cell is run. This means that
1409 matplotlib figures automatically after each cell is run. This means that
1398 plots in different cells won't interfere. Sometimes, you may want to make
1410 plots in different cells won't interfere. Sometimes, you may want to make
1399 a plot in one cell and then refine it in later cells. This can be accomplished
1411 a plot in one cell and then refine it in later cells. This can be accomplished
1400 by::
1412 by::
1401
1413
1402 In [1]: set_matplotlib_close(False)
1414 In [1]: set_matplotlib_close(False)
1403
1415
1404 To set this in your config files use the following::
1416 To set this in your config files use the following::
1405
1417
1406 c.InlineBackend.close_figures = False
1418 c.InlineBackend.close_figures = False
1407
1419
1408 Parameters
1420 Parameters
1409 ----------
1421 ----------
1410 close : bool
1422 close : bool
1411 Should all matplotlib figures be automatically closed after each cell is
1423 Should all matplotlib figures be automatically closed after each cell is
1412 run?
1424 run?
1413 """
1425 """
1414 from ipykernel.pylab.config import InlineBackend
1426 from ipykernel.pylab.config import InlineBackend
1415 cfg = InlineBackend.instance()
1427 cfg = InlineBackend.instance()
1416 cfg.close_figures = close
1428 cfg.close_figures = close
@@ -1,229 +1,229 b''
1 """Hooks for IPython.
1 """Hooks for IPython.
2
2
3 In Python, it is possible to overwrite any method of any object if you really
3 In Python, it is possible to overwrite any method of any object if you really
4 want to. But IPython exposes a few 'hooks', methods which are *designed* to
4 want to. But IPython exposes a few 'hooks', methods which are *designed* to
5 be overwritten by users for customization purposes. This module defines the
5 be overwritten by users for customization purposes. This module defines the
6 default versions of all such hooks, which get used by IPython if not
6 default versions of all such hooks, which get used by IPython if not
7 overridden by the user.
7 overridden by the user.
8
8
9 Hooks are simple functions, but they should be declared with ``self`` as their
9 Hooks are simple functions, but they should be declared with ``self`` as their
10 first argument, because when activated they are registered into IPython as
10 first argument, because when activated they are registered into IPython as
11 instance methods. The self argument will be the IPython running instance
11 instance methods. The self argument will be the IPython running instance
12 itself, so hooks have full access to the entire IPython object.
12 itself, so hooks have full access to the entire IPython object.
13
13
14 If you wish to define a new hook and activate it, you can make an :doc:`extension
14 If you wish to define a new hook and activate it, you can make an :doc:`extension
15 </config/extensions/index>` or a :ref:`startup script <startup_files>`. For
15 </config/extensions/index>` or a :ref:`startup script <startup_files>`. For
16 example, you could use a startup file like this::
16 example, you could use a startup file like this::
17
17
18 import os
18 import os
19
19
20 def calljed(self,filename, linenum):
20 def calljed(self,filename, linenum):
21 "My editor hook calls the jed editor directly."
21 "My editor hook calls the jed editor directly."
22 print "Calling my own editor, jed ..."
22 print "Calling my own editor, jed ..."
23 if os.system('jed +%d %s' % (linenum,filename)) != 0:
23 if os.system('jed +%d %s' % (linenum,filename)) != 0:
24 raise TryNext()
24 raise TryNext()
25
25
26 def load_ipython_extension(ip):
26 def load_ipython_extension(ip):
27 ip.set_hook('editor', calljed)
27 ip.set_hook('editor', calljed)
28
28
29 """
29 """
30
30
31 #*****************************************************************************
31 #*****************************************************************************
32 # Copyright (C) 2005 Fernando Perez. <fperez@colorado.edu>
32 # Copyright (C) 2005 Fernando Perez. <fperez@colorado.edu>
33 #
33 #
34 # Distributed under the terms of the BSD License. The full license is in
34 # Distributed under the terms of the BSD License. The full license is in
35 # the file COPYING, distributed as part of this software.
35 # the file COPYING, distributed as part of this software.
36 #*****************************************************************************
36 #*****************************************************************************
37
37
38 import os
38 import os
39 import subprocess
39 import subprocess
40 import warnings
40 import warnings
41 import sys
41 import sys
42
42
43 from IPython.core.error import TryNext
43 from IPython.core.error import TryNext
44
44
45 # List here all the default hooks. For now it's just the editor functions
45 # List here all the default hooks. For now it's just the editor functions
46 # but over time we'll move here all the public API for user-accessible things.
46 # but over time we'll move here all the public API for user-accessible things.
47
47
48 __all__ = ['editor', 'synchronize_with_editor',
48 __all__ = ['editor', 'synchronize_with_editor',
49 'shutdown_hook', 'late_startup_hook',
49 'shutdown_hook', 'late_startup_hook',
50 'show_in_pager','pre_prompt_hook',
50 'show_in_pager','pre_prompt_hook',
51 'pre_run_code_hook', 'clipboard_get']
51 'pre_run_code_hook', 'clipboard_get']
52
52
53 deprecated = {'pre_run_code_hook': "a callback for the 'pre_execute' or 'pre_run_cell' event",
53 deprecated = {'pre_run_code_hook': "a callback for the 'pre_execute' or 'pre_run_cell' event",
54 'late_startup_hook': "a callback for the 'shell_initialized' event",
54 'late_startup_hook': "a callback for the 'shell_initialized' event",
55 'shutdown_hook': "the atexit module",
55 'shutdown_hook': "the atexit module",
56 }
56 }
57
57
58 def editor(self, filename, linenum=None, wait=True):
58 def editor(self, filename, linenum=None, wait=True):
59 """Open the default editor at the given filename and linenumber.
59 """Open the default editor at the given filename and linenumber.
60
60
61 This is IPython's default editor hook, you can use it as an example to
61 This is IPython's default editor hook, you can use it as an example to
62 write your own modified one. To set your own editor function as the
62 write your own modified one. To set your own editor function as the
63 new editor hook, call ip.set_hook('editor',yourfunc)."""
63 new editor hook, call ip.set_hook('editor',yourfunc)."""
64
64
65 # IPython configures a default editor at startup by reading $EDITOR from
65 # IPython configures a default editor at startup by reading $EDITOR from
66 # the environment, and falling back on vi (unix) or notepad (win32).
66 # the environment, and falling back on vi (unix) or notepad (win32).
67 editor = self.editor
67 editor = self.editor
68
68
69 # marker for at which line to open the file (for existing objects)
69 # marker for at which line to open the file (for existing objects)
70 if linenum is None or editor=='notepad':
70 if linenum is None or editor=='notepad':
71 linemark = ''
71 linemark = ''
72 else:
72 else:
73 linemark = '+%d' % int(linenum)
73 linemark = '+%d' % int(linenum)
74
74
75 # Enclose in quotes if necessary and legal
75 # Enclose in quotes if necessary and legal
76 if ' ' in editor and os.path.isfile(editor) and editor[0] != '"':
76 if ' ' in editor and os.path.isfile(editor) and editor[0] != '"':
77 editor = '"%s"' % editor
77 editor = '"%s"' % editor
78
78
79 # Call the actual editor
79 # Call the actual editor
80 proc = subprocess.Popen('%s %s %s' % (editor, linemark, filename),
80 proc = subprocess.Popen('%s %s %s' % (editor, linemark, filename),
81 shell=True)
81 shell=True)
82 if wait and proc.wait() != 0:
82 if wait and proc.wait() != 0:
83 raise TryNext()
83 raise TryNext()
84
84
85 import tempfile
85 import tempfile
86 from IPython.utils.decorators import undoc
86 from IPython.utils.decorators import undoc
87
87
88 @undoc
88 @undoc
89 def fix_error_editor(self,filename,linenum,column,msg):
89 def fix_error_editor(self,filename,linenum,column,msg):
90 """DEPRECATED
90 """DEPRECATED
91
91
92 Open the editor at the given filename, linenumber, column and
92 Open the editor at the given filename, linenumber, column and
93 show an error message. This is used for correcting syntax errors.
93 show an error message. This is used for correcting syntax errors.
94 The current implementation only has special support for the VIM editor,
94 The current implementation only has special support for the VIM editor,
95 and falls back on the 'editor' hook if VIM is not used.
95 and falls back on the 'editor' hook if VIM is not used.
96
96
97 Call ip.set_hook('fix_error_editor',yourfunc) to use your own function,
97 Call ip.set_hook('fix_error_editor',yourfunc) to use your own function,
98 """
98 """
99
99
100 warnings.warn("""
100 warnings.warn("""
101 `fix_error_editor` is deprecated as of IPython 6.0 and will be removed
101 `fix_error_editor` is deprecated as of IPython 6.0 and will be removed
102 in future versions. It appears to be used only for automatically fixing syntax
102 in future versions. It appears to be used only for automatically fixing syntax
103 error that has been broken for a few years and has thus been removed. If you
103 error that has been broken for a few years and has thus been removed. If you
104 happened to use this function and still need it please make your voice heard on
104 happened to use this function and still need it please make your voice heard on
105 the mailing list ipython-dev@python.org , or on the GitHub Issue tracker:
105 the mailing list ipython-dev@python.org , or on the GitHub Issue tracker:
106 https://github.com/ipython/ipython/issues/9649 """, UserWarning)
106 https://github.com/ipython/ipython/issues/9649 """, UserWarning)
107
107
108 def vim_quickfix_file():
108 def vim_quickfix_file():
109 t = tempfile.NamedTemporaryFile()
109 t = tempfile.NamedTemporaryFile()
110 t.write('%s:%d:%d:%s\n' % (filename,linenum,column,msg))
110 t.write('%s:%d:%d:%s\n' % (filename,linenum,column,msg))
111 t.flush()
111 t.flush()
112 return t
112 return t
113 if os.path.basename(self.editor) != 'vim':
113 if os.path.basename(self.editor) != 'vim':
114 self.hooks.editor(filename,linenum)
114 self.hooks.editor(filename,linenum)
115 return
115 return
116 t = vim_quickfix_file()
116 t = vim_quickfix_file()
117 try:
117 try:
118 if os.system('vim --cmd "set errorformat=%f:%l:%c:%m" -q ' + t.name):
118 if os.system('vim --cmd "set errorformat=%f:%l:%c:%m" -q ' + t.name):
119 raise TryNext()
119 raise TryNext()
120 finally:
120 finally:
121 t.close()
121 t.close()
122
122
123
123
124 def synchronize_with_editor(self, filename, linenum, column):
124 def synchronize_with_editor(self, filename, linenum, column):
125 pass
125 pass
126
126
127
127
128 class CommandChainDispatcher:
128 class CommandChainDispatcher:
129 """ Dispatch calls to a chain of commands until some func can handle it
129 """ Dispatch calls to a chain of commands until some func can handle it
130
130
131 Usage: instantiate, execute "add" to add commands (with optional
131 Usage: instantiate, execute "add" to add commands (with optional
132 priority), execute normally via f() calling mechanism.
132 priority), execute normally via f() calling mechanism.
133
133
134 """
134 """
135 def __init__(self,commands=None):
135 def __init__(self,commands=None):
136 if commands is None:
136 if commands is None:
137 self.chain = []
137 self.chain = []
138 else:
138 else:
139 self.chain = commands
139 self.chain = commands
140
140
141
141
142 def __call__(self,*args, **kw):
142 def __call__(self,*args, **kw):
143 """ Command chain is called just like normal func.
143 """ Command chain is called just like normal func.
144
144
145 This will call all funcs in chain with the same args as were given to
145 This will call all funcs in chain with the same args as were given to
146 this function, and return the result of first func that didn't raise
146 this function, and return the result of first func that didn't raise
147 TryNext"""
147 TryNext"""
148 last_exc = TryNext()
148 last_exc = TryNext()
149 for prio,cmd in self.chain:
149 for prio,cmd in self.chain:
150 #print "prio",prio,"cmd",cmd #dbg
150 #print "prio",prio,"cmd",cmd #dbg
151 try:
151 try:
152 return cmd(*args, **kw)
152 return cmd(*args, **kw)
153 except TryNext as exc:
153 except TryNext as exc:
154 last_exc = exc
154 last_exc = exc
155 # if no function will accept it, raise TryNext up to the caller
155 # if no function will accept it, raise TryNext up to the caller
156 raise last_exc
156 raise last_exc
157
157
158 def __str__(self):
158 def __str__(self):
159 return str(self.chain)
159 return str(self.chain)
160
160
161 def add(self, func, priority=0):
161 def add(self, func, priority=0):
162 """ Add a func to the cmd chain with given priority """
162 """ Add a func to the cmd chain with given priority """
163 self.chain.append((priority, func))
163 self.chain.append((priority, func))
164 self.chain.sort(key=lambda x: x[0])
164 self.chain.sort(key=lambda x: x[0])
165
165
166 def __iter__(self):
166 def __iter__(self):
167 """ Return all objects in chain.
167 """ Return all objects in chain.
168
168
169 Handy if the objects are not callable.
169 Handy if the objects are not callable.
170 """
170 """
171 return iter(self.chain)
171 return iter(self.chain)
172
172
173
173
174 def shutdown_hook(self):
174 def shutdown_hook(self):
175 """ default shutdown hook
175 """ default shutdown hook
176
176
177 Typically, shotdown hooks should raise TryNext so all shutdown ops are done
177 Typically, shutdown hooks should raise TryNext so all shutdown ops are done
178 """
178 """
179
179
180 #print "default shutdown hook ok" # dbg
180 #print "default shutdown hook ok" # dbg
181 return
181 return
182
182
183
183
184 def late_startup_hook(self):
184 def late_startup_hook(self):
185 """ Executed after ipython has been constructed and configured
185 """ Executed after ipython has been constructed and configured
186
186
187 """
187 """
188 #print "default startup hook ok" # dbg
188 #print "default startup hook ok" # dbg
189
189
190
190
191 def show_in_pager(self, data, start, screen_lines):
191 def show_in_pager(self, data, start, screen_lines):
192 """ Run a string through pager """
192 """ Run a string through pager """
193 # raising TryNext here will use the default paging functionality
193 # raising TryNext here will use the default paging functionality
194 raise TryNext
194 raise TryNext
195
195
196
196
197 def pre_prompt_hook(self):
197 def pre_prompt_hook(self):
198 """ Run before displaying the next prompt
198 """ Run before displaying the next prompt
199
199
200 Use this e.g. to display output from asynchronous operations (in order
200 Use this e.g. to display output from asynchronous operations (in order
201 to not mess up text entry)
201 to not mess up text entry)
202 """
202 """
203
203
204 return None
204 return None
205
205
206
206
207 def pre_run_code_hook(self):
207 def pre_run_code_hook(self):
208 """ Executed before running the (prefiltered) code in IPython """
208 """ Executed before running the (prefiltered) code in IPython """
209 return None
209 return None
210
210
211
211
212 def clipboard_get(self):
212 def clipboard_get(self):
213 """ Get text from the clipboard.
213 """ Get text from the clipboard.
214 """
214 """
215 from IPython.lib.clipboard import (
215 from IPython.lib.clipboard import (
216 osx_clipboard_get, tkinter_clipboard_get,
216 osx_clipboard_get, tkinter_clipboard_get,
217 win32_clipboard_get
217 win32_clipboard_get
218 )
218 )
219 if sys.platform == 'win32':
219 if sys.platform == 'win32':
220 chain = [win32_clipboard_get, tkinter_clipboard_get]
220 chain = [win32_clipboard_get, tkinter_clipboard_get]
221 elif sys.platform == 'darwin':
221 elif sys.platform == 'darwin':
222 chain = [osx_clipboard_get, tkinter_clipboard_get]
222 chain = [osx_clipboard_get, tkinter_clipboard_get]
223 else:
223 else:
224 chain = [tkinter_clipboard_get]
224 chain = [tkinter_clipboard_get]
225 dispatcher = CommandChainDispatcher()
225 dispatcher = CommandChainDispatcher()
226 for func in chain:
226 for func in chain:
227 dispatcher.add(func)
227 dispatcher.add(func)
228 text = dispatcher()
228 text = dispatcher()
229 return text
229 return text
@@ -1,773 +1,773 b''
1 """DEPRECATED: Input handling and transformation machinery.
1 """DEPRECATED: Input handling and transformation machinery.
2
2
3 This module was deprecated in IPython 7.0, in favour of inputtransformer2.
3 This module was deprecated in IPython 7.0, in favour of inputtransformer2.
4
4
5 The first class in this module, :class:`InputSplitter`, is designed to tell when
5 The first class in this module, :class:`InputSplitter`, is designed to tell when
6 input from a line-oriented frontend is complete and should be executed, and when
6 input from a line-oriented frontend is complete and should be executed, and when
7 the user should be prompted for another line of code instead. The name 'input
7 the user should be prompted for another line of code instead. The name 'input
8 splitter' is largely for historical reasons.
8 splitter' is largely for historical reasons.
9
9
10 A companion, :class:`IPythonInputSplitter`, provides the same functionality but
10 A companion, :class:`IPythonInputSplitter`, provides the same functionality but
11 with full support for the extended IPython syntax (magics, system calls, etc).
11 with full support for the extended IPython syntax (magics, system calls, etc).
12 The code to actually do these transformations is in :mod:`IPython.core.inputtransformer`.
12 The code to actually do these transformations is in :mod:`IPython.core.inputtransformer`.
13 :class:`IPythonInputSplitter` feeds the raw code to the transformers in order
13 :class:`IPythonInputSplitter` feeds the raw code to the transformers in order
14 and stores the results.
14 and stores the results.
15
15
16 For more details, see the class docstrings below.
16 For more details, see the class docstrings below.
17 """
17 """
18
18
19 from warnings import warn
19 from warnings import warn
20
20
21 warn('IPython.core.inputsplitter is deprecated since IPython 7 in favor of `IPython.core.inputtransformer2`',
21 warn('IPython.core.inputsplitter is deprecated since IPython 7 in favor of `IPython.core.inputtransformer2`',
22 DeprecationWarning)
22 DeprecationWarning)
23
23
24 # Copyright (c) IPython Development Team.
24 # Copyright (c) IPython Development Team.
25 # Distributed under the terms of the Modified BSD License.
25 # Distributed under the terms of the Modified BSD License.
26 import ast
26 import ast
27 import codeop
27 import codeop
28 import io
28 import io
29 import re
29 import re
30 import sys
30 import sys
31 import tokenize
31 import tokenize
32 import warnings
32 import warnings
33
33
34 from IPython.utils.py3compat import cast_unicode
34 from IPython.utils.py3compat import cast_unicode
35 from IPython.core.inputtransformer import (leading_indent,
35 from IPython.core.inputtransformer import (leading_indent,
36 classic_prompt,
36 classic_prompt,
37 ipy_prompt,
37 ipy_prompt,
38 cellmagic,
38 cellmagic,
39 assemble_logical_lines,
39 assemble_logical_lines,
40 help_end,
40 help_end,
41 escaped_commands,
41 escaped_commands,
42 assign_from_magic,
42 assign_from_magic,
43 assign_from_system,
43 assign_from_system,
44 assemble_python_lines,
44 assemble_python_lines,
45 )
45 )
46
46
47 # These are available in this module for backwards compatibility.
47 # These are available in this module for backwards compatibility.
48 from IPython.core.inputtransformer import (ESC_SHELL, ESC_SH_CAP, ESC_HELP,
48 from IPython.core.inputtransformer import (ESC_SHELL, ESC_SH_CAP, ESC_HELP,
49 ESC_HELP2, ESC_MAGIC, ESC_MAGIC2,
49 ESC_HELP2, ESC_MAGIC, ESC_MAGIC2,
50 ESC_QUOTE, ESC_QUOTE2, ESC_PAREN, ESC_SEQUENCES)
50 ESC_QUOTE, ESC_QUOTE2, ESC_PAREN, ESC_SEQUENCES)
51
51
52 #-----------------------------------------------------------------------------
52 #-----------------------------------------------------------------------------
53 # Utilities
53 # Utilities
54 #-----------------------------------------------------------------------------
54 #-----------------------------------------------------------------------------
55
55
56 # FIXME: These are general-purpose utilities that later can be moved to the
56 # FIXME: These are general-purpose utilities that later can be moved to the
57 # general ward. Kept here for now because we're being very strict about test
57 # general ward. Kept here for now because we're being very strict about test
58 # coverage with this code, and this lets us ensure that we keep 100% coverage
58 # coverage with this code, and this lets us ensure that we keep 100% coverage
59 # while developing.
59 # while developing.
60
60
61 # compiled regexps for autoindent management
61 # compiled regexps for autoindent management
62 dedent_re = re.compile('|'.join([
62 dedent_re = re.compile('|'.join([
63 r'^\s+raise(\s.*)?$', # raise statement (+ space + other stuff, maybe)
63 r'^\s+raise(\s.*)?$', # raise statement (+ space + other stuff, maybe)
64 r'^\s+raise\([^\)]*\).*$', # wacky raise with immediate open paren
64 r'^\s+raise\([^\)]*\).*$', # wacky raise with immediate open paren
65 r'^\s+return(\s.*)?$', # normal return (+ space + other stuff, maybe)
65 r'^\s+return(\s.*)?$', # normal return (+ space + other stuff, maybe)
66 r'^\s+return\([^\)]*\).*$', # wacky return with immediate open paren
66 r'^\s+return\([^\)]*\).*$', # wacky return with immediate open paren
67 r'^\s+pass\s*$', # pass (optionally followed by trailing spaces)
67 r'^\s+pass\s*$', # pass (optionally followed by trailing spaces)
68 r'^\s+break\s*$', # break (optionally followed by trailing spaces)
68 r'^\s+break\s*$', # break (optionally followed by trailing spaces)
69 r'^\s+continue\s*$', # continue (optionally followed by trailing spaces)
69 r'^\s+continue\s*$', # continue (optionally followed by trailing spaces)
70 ]))
70 ]))
71 ini_spaces_re = re.compile(r'^([ \t\r\f\v]+)')
71 ini_spaces_re = re.compile(r'^([ \t\r\f\v]+)')
72
72
73 # regexp to match pure comment lines so we don't accidentally insert 'if 1:'
73 # regexp to match pure comment lines so we don't accidentally insert 'if 1:'
74 # before pure comments
74 # before pure comments
75 comment_line_re = re.compile('^\s*\#')
75 comment_line_re = re.compile(r'^\s*\#')
76
76
77
77
78 def num_ini_spaces(s):
78 def num_ini_spaces(s):
79 """Return the number of initial spaces in a string.
79 """Return the number of initial spaces in a string.
80
80
81 Note that tabs are counted as a single space. For now, we do *not* support
81 Note that tabs are counted as a single space. For now, we do *not* support
82 mixing of tabs and spaces in the user's input.
82 mixing of tabs and spaces in the user's input.
83
83
84 Parameters
84 Parameters
85 ----------
85 ----------
86 s : string
86 s : string
87
87
88 Returns
88 Returns
89 -------
89 -------
90 n : int
90 n : int
91 """
91 """
92
92
93 ini_spaces = ini_spaces_re.match(s)
93 ini_spaces = ini_spaces_re.match(s)
94 if ini_spaces:
94 if ini_spaces:
95 return ini_spaces.end()
95 return ini_spaces.end()
96 else:
96 else:
97 return 0
97 return 0
98
98
99 # Fake token types for partial_tokenize:
99 # Fake token types for partial_tokenize:
100 INCOMPLETE_STRING = tokenize.N_TOKENS
100 INCOMPLETE_STRING = tokenize.N_TOKENS
101 IN_MULTILINE_STATEMENT = tokenize.N_TOKENS + 1
101 IN_MULTILINE_STATEMENT = tokenize.N_TOKENS + 1
102
102
103 # The 2 classes below have the same API as TokenInfo, but don't try to look up
103 # The 2 classes below have the same API as TokenInfo, but don't try to look up
104 # a token type name that they won't find.
104 # a token type name that they won't find.
105 class IncompleteString:
105 class IncompleteString:
106 type = exact_type = INCOMPLETE_STRING
106 type = exact_type = INCOMPLETE_STRING
107 def __init__(self, s, start, end, line):
107 def __init__(self, s, start, end, line):
108 self.s = s
108 self.s = s
109 self.start = start
109 self.start = start
110 self.end = end
110 self.end = end
111 self.line = line
111 self.line = line
112
112
113 class InMultilineStatement:
113 class InMultilineStatement:
114 type = exact_type = IN_MULTILINE_STATEMENT
114 type = exact_type = IN_MULTILINE_STATEMENT
115 def __init__(self, pos, line):
115 def __init__(self, pos, line):
116 self.s = ''
116 self.s = ''
117 self.start = self.end = pos
117 self.start = self.end = pos
118 self.line = line
118 self.line = line
119
119
120 def partial_tokens(s):
120 def partial_tokens(s):
121 """Iterate over tokens from a possibly-incomplete string of code.
121 """Iterate over tokens from a possibly-incomplete string of code.
122
122
123 This adds two special token types: INCOMPLETE_STRING and
123 This adds two special token types: INCOMPLETE_STRING and
124 IN_MULTILINE_STATEMENT. These can only occur as the last token yielded, and
124 IN_MULTILINE_STATEMENT. These can only occur as the last token yielded, and
125 represent the two main ways for code to be incomplete.
125 represent the two main ways for code to be incomplete.
126 """
126 """
127 readline = io.StringIO(s).readline
127 readline = io.StringIO(s).readline
128 token = tokenize.TokenInfo(tokenize.NEWLINE, '', (1, 0), (1, 0), '')
128 token = tokenize.TokenInfo(tokenize.NEWLINE, '', (1, 0), (1, 0), '')
129 try:
129 try:
130 for token in tokenize.generate_tokens(readline):
130 for token in tokenize.generate_tokens(readline):
131 yield token
131 yield token
132 except tokenize.TokenError as e:
132 except tokenize.TokenError as e:
133 # catch EOF error
133 # catch EOF error
134 lines = s.splitlines(keepends=True)
134 lines = s.splitlines(keepends=True)
135 end = len(lines), len(lines[-1])
135 end = len(lines), len(lines[-1])
136 if 'multi-line string' in e.args[0]:
136 if 'multi-line string' in e.args[0]:
137 l, c = start = token.end
137 l, c = start = token.end
138 s = lines[l-1][c:] + ''.join(lines[l:])
138 s = lines[l-1][c:] + ''.join(lines[l:])
139 yield IncompleteString(s, start, end, lines[-1])
139 yield IncompleteString(s, start, end, lines[-1])
140 elif 'multi-line statement' in e.args[0]:
140 elif 'multi-line statement' in e.args[0]:
141 yield InMultilineStatement(end, lines[-1])
141 yield InMultilineStatement(end, lines[-1])
142 else:
142 else:
143 raise
143 raise
144
144
145 def find_next_indent(code):
145 def find_next_indent(code):
146 """Find the number of spaces for the next line of indentation"""
146 """Find the number of spaces for the next line of indentation"""
147 tokens = list(partial_tokens(code))
147 tokens = list(partial_tokens(code))
148 if tokens[-1].type == tokenize.ENDMARKER:
148 if tokens[-1].type == tokenize.ENDMARKER:
149 tokens.pop()
149 tokens.pop()
150 if not tokens:
150 if not tokens:
151 return 0
151 return 0
152 while (tokens[-1].type in {tokenize.DEDENT, tokenize.NEWLINE, tokenize.COMMENT}):
152 while (tokens[-1].type in {tokenize.DEDENT, tokenize.NEWLINE, tokenize.COMMENT}):
153 tokens.pop()
153 tokens.pop()
154
154
155 if tokens[-1].type == INCOMPLETE_STRING:
155 if tokens[-1].type == INCOMPLETE_STRING:
156 # Inside a multiline string
156 # Inside a multiline string
157 return 0
157 return 0
158
158
159 # Find the indents used before
159 # Find the indents used before
160 prev_indents = [0]
160 prev_indents = [0]
161 def _add_indent(n):
161 def _add_indent(n):
162 if n != prev_indents[-1]:
162 if n != prev_indents[-1]:
163 prev_indents.append(n)
163 prev_indents.append(n)
164
164
165 tokiter = iter(tokens)
165 tokiter = iter(tokens)
166 for tok in tokiter:
166 for tok in tokiter:
167 if tok.type in {tokenize.INDENT, tokenize.DEDENT}:
167 if tok.type in {tokenize.INDENT, tokenize.DEDENT}:
168 _add_indent(tok.end[1])
168 _add_indent(tok.end[1])
169 elif (tok.type == tokenize.NL):
169 elif (tok.type == tokenize.NL):
170 try:
170 try:
171 _add_indent(next(tokiter).start[1])
171 _add_indent(next(tokiter).start[1])
172 except StopIteration:
172 except StopIteration:
173 break
173 break
174
174
175 last_indent = prev_indents.pop()
175 last_indent = prev_indents.pop()
176
176
177 # If we've just opened a multiline statement (e.g. 'a = ['), indent more
177 # If we've just opened a multiline statement (e.g. 'a = ['), indent more
178 if tokens[-1].type == IN_MULTILINE_STATEMENT:
178 if tokens[-1].type == IN_MULTILINE_STATEMENT:
179 if tokens[-2].exact_type in {tokenize.LPAR, tokenize.LSQB, tokenize.LBRACE}:
179 if tokens[-2].exact_type in {tokenize.LPAR, tokenize.LSQB, tokenize.LBRACE}:
180 return last_indent + 4
180 return last_indent + 4
181 return last_indent
181 return last_indent
182
182
183 if tokens[-1].exact_type == tokenize.COLON:
183 if tokens[-1].exact_type == tokenize.COLON:
184 # Line ends with colon - indent
184 # Line ends with colon - indent
185 return last_indent + 4
185 return last_indent + 4
186
186
187 if last_indent:
187 if last_indent:
188 # Examine the last line for dedent cues - statements like return or
188 # Examine the last line for dedent cues - statements like return or
189 # raise which normally end a block of code.
189 # raise which normally end a block of code.
190 last_line_starts = 0
190 last_line_starts = 0
191 for i, tok in enumerate(tokens):
191 for i, tok in enumerate(tokens):
192 if tok.type == tokenize.NEWLINE:
192 if tok.type == tokenize.NEWLINE:
193 last_line_starts = i + 1
193 last_line_starts = i + 1
194
194
195 last_line_tokens = tokens[last_line_starts:]
195 last_line_tokens = tokens[last_line_starts:]
196 names = [t.string for t in last_line_tokens if t.type == tokenize.NAME]
196 names = [t.string for t in last_line_tokens if t.type == tokenize.NAME]
197 if names and names[0] in {'raise', 'return', 'pass', 'break', 'continue'}:
197 if names and names[0] in {'raise', 'return', 'pass', 'break', 'continue'}:
198 # Find the most recent indentation less than the current level
198 # Find the most recent indentation less than the current level
199 for indent in reversed(prev_indents):
199 for indent in reversed(prev_indents):
200 if indent < last_indent:
200 if indent < last_indent:
201 return indent
201 return indent
202
202
203 return last_indent
203 return last_indent
204
204
205
205
206 def last_blank(src):
206 def last_blank(src):
207 """Determine if the input source ends in a blank.
207 """Determine if the input source ends in a blank.
208
208
209 A blank is either a newline or a line consisting of whitespace.
209 A blank is either a newline or a line consisting of whitespace.
210
210
211 Parameters
211 Parameters
212 ----------
212 ----------
213 src : string
213 src : string
214 A single or multiline string.
214 A single or multiline string.
215 """
215 """
216 if not src: return False
216 if not src: return False
217 ll = src.splitlines()[-1]
217 ll = src.splitlines()[-1]
218 return (ll == '') or ll.isspace()
218 return (ll == '') or ll.isspace()
219
219
220
220
221 last_two_blanks_re = re.compile(r'\n\s*\n\s*$', re.MULTILINE)
221 last_two_blanks_re = re.compile(r'\n\s*\n\s*$', re.MULTILINE)
222 last_two_blanks_re2 = re.compile(r'.+\n\s*\n\s+$', re.MULTILINE)
222 last_two_blanks_re2 = re.compile(r'.+\n\s*\n\s+$', re.MULTILINE)
223
223
224 def last_two_blanks(src):
224 def last_two_blanks(src):
225 """Determine if the input source ends in two blanks.
225 """Determine if the input source ends in two blanks.
226
226
227 A blank is either a newline or a line consisting of whitespace.
227 A blank is either a newline or a line consisting of whitespace.
228
228
229 Parameters
229 Parameters
230 ----------
230 ----------
231 src : string
231 src : string
232 A single or multiline string.
232 A single or multiline string.
233 """
233 """
234 if not src: return False
234 if not src: return False
235 # The logic here is tricky: I couldn't get a regexp to work and pass all
235 # The logic here is tricky: I couldn't get a regexp to work and pass all
236 # the tests, so I took a different approach: split the source by lines,
236 # the tests, so I took a different approach: split the source by lines,
237 # grab the last two and prepend '###\n' as a stand-in for whatever was in
237 # grab the last two and prepend '###\n' as a stand-in for whatever was in
238 # the body before the last two lines. Then, with that structure, it's
238 # the body before the last two lines. Then, with that structure, it's
239 # possible to analyze with two regexps. Not the most elegant solution, but
239 # possible to analyze with two regexps. Not the most elegant solution, but
240 # it works. If anyone tries to change this logic, make sure to validate
240 # it works. If anyone tries to change this logic, make sure to validate
241 # the whole test suite first!
241 # the whole test suite first!
242 new_src = '\n'.join(['###\n'] + src.splitlines()[-2:])
242 new_src = '\n'.join(['###\n'] + src.splitlines()[-2:])
243 return (bool(last_two_blanks_re.match(new_src)) or
243 return (bool(last_two_blanks_re.match(new_src)) or
244 bool(last_two_blanks_re2.match(new_src)) )
244 bool(last_two_blanks_re2.match(new_src)) )
245
245
246
246
247 def remove_comments(src):
247 def remove_comments(src):
248 """Remove all comments from input source.
248 """Remove all comments from input source.
249
249
250 Note: comments are NOT recognized inside of strings!
250 Note: comments are NOT recognized inside of strings!
251
251
252 Parameters
252 Parameters
253 ----------
253 ----------
254 src : string
254 src : string
255 A single or multiline input string.
255 A single or multiline input string.
256
256
257 Returns
257 Returns
258 -------
258 -------
259 String with all Python comments removed.
259 String with all Python comments removed.
260 """
260 """
261
261
262 return re.sub('#.*', '', src)
262 return re.sub('#.*', '', src)
263
263
264
264
265 def get_input_encoding():
265 def get_input_encoding():
266 """Return the default standard input encoding.
266 """Return the default standard input encoding.
267
267
268 If sys.stdin has no encoding, 'ascii' is returned."""
268 If sys.stdin has no encoding, 'ascii' is returned."""
269 # There are strange environments for which sys.stdin.encoding is None. We
269 # There are strange environments for which sys.stdin.encoding is None. We
270 # ensure that a valid encoding is returned.
270 # ensure that a valid encoding is returned.
271 encoding = getattr(sys.stdin, 'encoding', None)
271 encoding = getattr(sys.stdin, 'encoding', None)
272 if encoding is None:
272 if encoding is None:
273 encoding = 'ascii'
273 encoding = 'ascii'
274 return encoding
274 return encoding
275
275
276 #-----------------------------------------------------------------------------
276 #-----------------------------------------------------------------------------
277 # Classes and functions for normal Python syntax handling
277 # Classes and functions for normal Python syntax handling
278 #-----------------------------------------------------------------------------
278 #-----------------------------------------------------------------------------
279
279
280 class InputSplitter(object):
280 class InputSplitter(object):
281 r"""An object that can accumulate lines of Python source before execution.
281 r"""An object that can accumulate lines of Python source before execution.
282
282
283 This object is designed to be fed python source line-by-line, using
283 This object is designed to be fed python source line-by-line, using
284 :meth:`push`. It will return on each push whether the currently pushed
284 :meth:`push`. It will return on each push whether the currently pushed
285 code could be executed already. In addition, it provides a method called
285 code could be executed already. In addition, it provides a method called
286 :meth:`push_accepts_more` that can be used to query whether more input
286 :meth:`push_accepts_more` that can be used to query whether more input
287 can be pushed into a single interactive block.
287 can be pushed into a single interactive block.
288
288
289 This is a simple example of how an interactive terminal-based client can use
289 This is a simple example of how an interactive terminal-based client can use
290 this tool::
290 this tool::
291
291
292 isp = InputSplitter()
292 isp = InputSplitter()
293 while isp.push_accepts_more():
293 while isp.push_accepts_more():
294 indent = ' '*isp.indent_spaces
294 indent = ' '*isp.indent_spaces
295 prompt = '>>> ' + indent
295 prompt = '>>> ' + indent
296 line = indent + raw_input(prompt)
296 line = indent + raw_input(prompt)
297 isp.push(line)
297 isp.push(line)
298 print 'Input source was:\n', isp.source_reset(),
298 print 'Input source was:\n', isp.source_reset(),
299 """
299 """
300 # A cache for storing the current indentation
300 # A cache for storing the current indentation
301 # The first value stores the most recently processed source input
301 # The first value stores the most recently processed source input
302 # The second value is the number of spaces for the current indentation
302 # The second value is the number of spaces for the current indentation
303 # If self.source matches the first value, the second value is a valid
303 # If self.source matches the first value, the second value is a valid
304 # current indentation. Otherwise, the cache is invalid and the indentation
304 # current indentation. Otherwise, the cache is invalid and the indentation
305 # must be recalculated.
305 # must be recalculated.
306 _indent_spaces_cache = None, None
306 _indent_spaces_cache = None, None
307 # String, indicating the default input encoding. It is computed by default
307 # String, indicating the default input encoding. It is computed by default
308 # at initialization time via get_input_encoding(), but it can be reset by a
308 # at initialization time via get_input_encoding(), but it can be reset by a
309 # client with specific knowledge of the encoding.
309 # client with specific knowledge of the encoding.
310 encoding = ''
310 encoding = ''
311 # String where the current full source input is stored, properly encoded.
311 # String where the current full source input is stored, properly encoded.
312 # Reading this attribute is the normal way of querying the currently pushed
312 # Reading this attribute is the normal way of querying the currently pushed
313 # source code, that has been properly encoded.
313 # source code, that has been properly encoded.
314 source = ''
314 source = ''
315 # Code object corresponding to the current source. It is automatically
315 # Code object corresponding to the current source. It is automatically
316 # synced to the source, so it can be queried at any time to obtain the code
316 # synced to the source, so it can be queried at any time to obtain the code
317 # object; it will be None if the source doesn't compile to valid Python.
317 # object; it will be None if the source doesn't compile to valid Python.
318 code = None
318 code = None
319
319
320 # Private attributes
320 # Private attributes
321
321
322 # List with lines of input accumulated so far
322 # List with lines of input accumulated so far
323 _buffer = None
323 _buffer = None
324 # Command compiler
324 # Command compiler
325 _compile = None
325 _compile = None
326 # Boolean indicating whether the current block is complete
326 # Boolean indicating whether the current block is complete
327 _is_complete = None
327 _is_complete = None
328 # Boolean indicating whether the current block has an unrecoverable syntax error
328 # Boolean indicating whether the current block has an unrecoverable syntax error
329 _is_invalid = False
329 _is_invalid = False
330
330
331 def __init__(self):
331 def __init__(self):
332 """Create a new InputSplitter instance.
332 """Create a new InputSplitter instance.
333 """
333 """
334 self._buffer = []
334 self._buffer = []
335 self._compile = codeop.CommandCompiler()
335 self._compile = codeop.CommandCompiler()
336 self.encoding = get_input_encoding()
336 self.encoding = get_input_encoding()
337
337
338 def reset(self):
338 def reset(self):
339 """Reset the input buffer and associated state."""
339 """Reset the input buffer and associated state."""
340 self._buffer[:] = []
340 self._buffer[:] = []
341 self.source = ''
341 self.source = ''
342 self.code = None
342 self.code = None
343 self._is_complete = False
343 self._is_complete = False
344 self._is_invalid = False
344 self._is_invalid = False
345
345
346 def source_reset(self):
346 def source_reset(self):
347 """Return the input source and perform a full reset.
347 """Return the input source and perform a full reset.
348 """
348 """
349 out = self.source
349 out = self.source
350 self.reset()
350 self.reset()
351 return out
351 return out
352
352
353 def check_complete(self, source):
353 def check_complete(self, source):
354 """Return whether a block of code is ready to execute, or should be continued
354 """Return whether a block of code is ready to execute, or should be continued
355
355
356 This is a non-stateful API, and will reset the state of this InputSplitter.
356 This is a non-stateful API, and will reset the state of this InputSplitter.
357
357
358 Parameters
358 Parameters
359 ----------
359 ----------
360 source : string
360 source : string
361 Python input code, which can be multiline.
361 Python input code, which can be multiline.
362
362
363 Returns
363 Returns
364 -------
364 -------
365 status : str
365 status : str
366 One of 'complete', 'incomplete', or 'invalid' if source is not a
366 One of 'complete', 'incomplete', or 'invalid' if source is not a
367 prefix of valid code.
367 prefix of valid code.
368 indent_spaces : int or None
368 indent_spaces : int or None
369 The number of spaces by which to indent the next line of code. If
369 The number of spaces by which to indent the next line of code. If
370 status is not 'incomplete', this is None.
370 status is not 'incomplete', this is None.
371 """
371 """
372 self.reset()
372 self.reset()
373 try:
373 try:
374 self.push(source)
374 self.push(source)
375 except SyntaxError:
375 except SyntaxError:
376 # Transformers in IPythonInputSplitter can raise SyntaxError,
376 # Transformers in IPythonInputSplitter can raise SyntaxError,
377 # which push() will not catch.
377 # which push() will not catch.
378 return 'invalid', None
378 return 'invalid', None
379 else:
379 else:
380 if self._is_invalid:
380 if self._is_invalid:
381 return 'invalid', None
381 return 'invalid', None
382 elif self.push_accepts_more():
382 elif self.push_accepts_more():
383 return 'incomplete', self.get_indent_spaces()
383 return 'incomplete', self.get_indent_spaces()
384 else:
384 else:
385 return 'complete', None
385 return 'complete', None
386 finally:
386 finally:
387 self.reset()
387 self.reset()
388
388
389 def push(self, lines):
389 def push(self, lines):
390 """Push one or more lines of input.
390 """Push one or more lines of input.
391
391
392 This stores the given lines and returns a status code indicating
392 This stores the given lines and returns a status code indicating
393 whether the code forms a complete Python block or not.
393 whether the code forms a complete Python block or not.
394
394
395 Any exceptions generated in compilation are swallowed, but if an
395 Any exceptions generated in compilation are swallowed, but if an
396 exception was produced, the method returns True.
396 exception was produced, the method returns True.
397
397
398 Parameters
398 Parameters
399 ----------
399 ----------
400 lines : string
400 lines : string
401 One or more lines of Python input.
401 One or more lines of Python input.
402
402
403 Returns
403 Returns
404 -------
404 -------
405 is_complete : boolean
405 is_complete : boolean
406 True if the current input source (the result of the current input
406 True if the current input source (the result of the current input
407 plus prior inputs) forms a complete Python execution block. Note that
407 plus prior inputs) forms a complete Python execution block. Note that
408 this value is also stored as a private attribute (``_is_complete``), so it
408 this value is also stored as a private attribute (``_is_complete``), so it
409 can be queried at any time.
409 can be queried at any time.
410 """
410 """
411 self._store(lines)
411 self._store(lines)
412 source = self.source
412 source = self.source
413
413
414 # Before calling _compile(), reset the code object to None so that if an
414 # Before calling _compile(), reset the code object to None so that if an
415 # exception is raised in compilation, we don't mislead by having
415 # exception is raised in compilation, we don't mislead by having
416 # inconsistent code/source attributes.
416 # inconsistent code/source attributes.
417 self.code, self._is_complete = None, None
417 self.code, self._is_complete = None, None
418 self._is_invalid = False
418 self._is_invalid = False
419
419
420 # Honor termination lines properly
420 # Honor termination lines properly
421 if source.endswith('\\\n'):
421 if source.endswith('\\\n'):
422 return False
422 return False
423
423
424 try:
424 try:
425 with warnings.catch_warnings():
425 with warnings.catch_warnings():
426 warnings.simplefilter('error', SyntaxWarning)
426 warnings.simplefilter('error', SyntaxWarning)
427 self.code = self._compile(source, symbol="exec")
427 self.code = self._compile(source, symbol="exec")
428 # Invalid syntax can produce any of a number of different errors from
428 # Invalid syntax can produce any of a number of different errors from
429 # inside the compiler, so we have to catch them all. Syntax errors
429 # inside the compiler, so we have to catch them all. Syntax errors
430 # immediately produce a 'ready' block, so the invalid Python can be
430 # immediately produce a 'ready' block, so the invalid Python can be
431 # sent to the kernel for evaluation with possible ipython
431 # sent to the kernel for evaluation with possible ipython
432 # special-syntax conversion.
432 # special-syntax conversion.
433 except (SyntaxError, OverflowError, ValueError, TypeError,
433 except (SyntaxError, OverflowError, ValueError, TypeError,
434 MemoryError, SyntaxWarning):
434 MemoryError, SyntaxWarning):
435 self._is_complete = True
435 self._is_complete = True
436 self._is_invalid = True
436 self._is_invalid = True
437 else:
437 else:
438 # Compilation didn't produce any exceptions (though it may not have
438 # Compilation didn't produce any exceptions (though it may not have
439 # given a complete code object)
439 # given a complete code object)
440 self._is_complete = self.code is not None
440 self._is_complete = self.code is not None
441
441
442 return self._is_complete
442 return self._is_complete
443
443
444 def push_accepts_more(self):
444 def push_accepts_more(self):
445 """Return whether a block of interactive input can accept more input.
445 """Return whether a block of interactive input can accept more input.
446
446
447 This method is meant to be used by line-oriented frontends, who need to
447 This method is meant to be used by line-oriented frontends, who need to
448 guess whether a block is complete or not based solely on prior and
448 guess whether a block is complete or not based solely on prior and
449 current input lines. The InputSplitter considers it has a complete
449 current input lines. The InputSplitter considers it has a complete
450 interactive block and will not accept more input when either:
450 interactive block and will not accept more input when either:
451
451
452 * A SyntaxError is raised
452 * A SyntaxError is raised
453
453
454 * The code is complete and consists of a single line or a single
454 * The code is complete and consists of a single line or a single
455 non-compound statement
455 non-compound statement
456
456
457 * The code is complete and has a blank line at the end
457 * The code is complete and has a blank line at the end
458
458
459 If the current input produces a syntax error, this method immediately
459 If the current input produces a syntax error, this method immediately
460 returns False but does *not* raise the syntax error exception, as
460 returns False but does *not* raise the syntax error exception, as
461 typically clients will want to send invalid syntax to an execution
461 typically clients will want to send invalid syntax to an execution
462 backend which might convert the invalid syntax into valid Python via
462 backend which might convert the invalid syntax into valid Python via
463 one of the dynamic IPython mechanisms.
463 one of the dynamic IPython mechanisms.
464 """
464 """
465
465
466 # With incomplete input, unconditionally accept more
466 # With incomplete input, unconditionally accept more
467 # A syntax error also sets _is_complete to True - see push()
467 # A syntax error also sets _is_complete to True - see push()
468 if not self._is_complete:
468 if not self._is_complete:
469 #print("Not complete") # debug
469 #print("Not complete") # debug
470 return True
470 return True
471
471
472 # The user can make any (complete) input execute by leaving a blank line
472 # The user can make any (complete) input execute by leaving a blank line
473 last_line = self.source.splitlines()[-1]
473 last_line = self.source.splitlines()[-1]
474 if (not last_line) or last_line.isspace():
474 if (not last_line) or last_line.isspace():
475 #print("Blank line") # debug
475 #print("Blank line") # debug
476 return False
476 return False
477
477
478 # If there's just a single line or AST node, and we're flush left, as is
478 # If there's just a single line or AST node, and we're flush left, as is
479 # the case after a simple statement such as 'a=1', we want to execute it
479 # the case after a simple statement such as 'a=1', we want to execute it
480 # straight away.
480 # straight away.
481 if self.get_indent_spaces() == 0:
481 if self.get_indent_spaces() == 0:
482 if len(self.source.splitlines()) <= 1:
482 if len(self.source.splitlines()) <= 1:
483 return False
483 return False
484
484
485 try:
485 try:
486 code_ast = ast.parse(u''.join(self._buffer))
486 code_ast = ast.parse(u''.join(self._buffer))
487 except Exception:
487 except Exception:
488 #print("Can't parse AST") # debug
488 #print("Can't parse AST") # debug
489 return False
489 return False
490 else:
490 else:
491 if len(code_ast.body) == 1 and \
491 if len(code_ast.body) == 1 and \
492 not hasattr(code_ast.body[0], 'body'):
492 not hasattr(code_ast.body[0], 'body'):
493 #print("Simple statement") # debug
493 #print("Simple statement") # debug
494 return False
494 return False
495
495
496 # General fallback - accept more code
496 # General fallback - accept more code
497 return True
497 return True
498
498
499 def get_indent_spaces(self):
499 def get_indent_spaces(self):
500 sourcefor, n = self._indent_spaces_cache
500 sourcefor, n = self._indent_spaces_cache
501 if sourcefor == self.source:
501 if sourcefor == self.source:
502 return n
502 return n
503
503
504 # self.source always has a trailing newline
504 # self.source always has a trailing newline
505 n = find_next_indent(self.source[:-1])
505 n = find_next_indent(self.source[:-1])
506 self._indent_spaces_cache = (self.source, n)
506 self._indent_spaces_cache = (self.source, n)
507 return n
507 return n
508
508
509 # Backwards compatibility. I think all code that used .indent_spaces was
509 # Backwards compatibility. I think all code that used .indent_spaces was
510 # inside IPython, but we can leave this here until IPython 7 in case any
510 # inside IPython, but we can leave this here until IPython 7 in case any
511 # other modules are using it. -TK, November 2017
511 # other modules are using it. -TK, November 2017
512 indent_spaces = property(get_indent_spaces)
512 indent_spaces = property(get_indent_spaces)
513
513
514 def _store(self, lines, buffer=None, store='source'):
514 def _store(self, lines, buffer=None, store='source'):
515 """Store one or more lines of input.
515 """Store one or more lines of input.
516
516
517 If input lines are not newline-terminated, a newline is automatically
517 If input lines are not newline-terminated, a newline is automatically
518 appended."""
518 appended."""
519
519
520 if buffer is None:
520 if buffer is None:
521 buffer = self._buffer
521 buffer = self._buffer
522
522
523 if lines.endswith('\n'):
523 if lines.endswith('\n'):
524 buffer.append(lines)
524 buffer.append(lines)
525 else:
525 else:
526 buffer.append(lines+'\n')
526 buffer.append(lines+'\n')
527 setattr(self, store, self._set_source(buffer))
527 setattr(self, store, self._set_source(buffer))
528
528
529 def _set_source(self, buffer):
529 def _set_source(self, buffer):
530 return u''.join(buffer)
530 return u''.join(buffer)
531
531
532
532
533 class IPythonInputSplitter(InputSplitter):
533 class IPythonInputSplitter(InputSplitter):
534 """An input splitter that recognizes all of IPython's special syntax."""
534 """An input splitter that recognizes all of IPython's special syntax."""
535
535
536 # String with raw, untransformed input.
536 # String with raw, untransformed input.
537 source_raw = ''
537 source_raw = ''
538
538
539 # Flag to track when a transformer has stored input that it hasn't given
539 # Flag to track when a transformer has stored input that it hasn't given
540 # back yet.
540 # back yet.
541 transformer_accumulating = False
541 transformer_accumulating = False
542
542
543 # Flag to track when assemble_python_lines has stored input that it hasn't
543 # Flag to track when assemble_python_lines has stored input that it hasn't
544 # given back yet.
544 # given back yet.
545 within_python_line = False
545 within_python_line = False
546
546
547 # Private attributes
547 # Private attributes
548
548
549 # List with lines of raw input accumulated so far.
549 # List with lines of raw input accumulated so far.
550 _buffer_raw = None
550 _buffer_raw = None
551
551
552 def __init__(self, line_input_checker=True, physical_line_transforms=None,
552 def __init__(self, line_input_checker=True, physical_line_transforms=None,
553 logical_line_transforms=None, python_line_transforms=None):
553 logical_line_transforms=None, python_line_transforms=None):
554 super(IPythonInputSplitter, self).__init__()
554 super(IPythonInputSplitter, self).__init__()
555 self._buffer_raw = []
555 self._buffer_raw = []
556 self._validate = True
556 self._validate = True
557
557
558 if physical_line_transforms is not None:
558 if physical_line_transforms is not None:
559 self.physical_line_transforms = physical_line_transforms
559 self.physical_line_transforms = physical_line_transforms
560 else:
560 else:
561 self.physical_line_transforms = [
561 self.physical_line_transforms = [
562 leading_indent(),
562 leading_indent(),
563 classic_prompt(),
563 classic_prompt(),
564 ipy_prompt(),
564 ipy_prompt(),
565 cellmagic(end_on_blank_line=line_input_checker),
565 cellmagic(end_on_blank_line=line_input_checker),
566 ]
566 ]
567
567
568 self.assemble_logical_lines = assemble_logical_lines()
568 self.assemble_logical_lines = assemble_logical_lines()
569 if logical_line_transforms is not None:
569 if logical_line_transforms is not None:
570 self.logical_line_transforms = logical_line_transforms
570 self.logical_line_transforms = logical_line_transforms
571 else:
571 else:
572 self.logical_line_transforms = [
572 self.logical_line_transforms = [
573 help_end(),
573 help_end(),
574 escaped_commands(),
574 escaped_commands(),
575 assign_from_magic(),
575 assign_from_magic(),
576 assign_from_system(),
576 assign_from_system(),
577 ]
577 ]
578
578
579 self.assemble_python_lines = assemble_python_lines()
579 self.assemble_python_lines = assemble_python_lines()
580 if python_line_transforms is not None:
580 if python_line_transforms is not None:
581 self.python_line_transforms = python_line_transforms
581 self.python_line_transforms = python_line_transforms
582 else:
582 else:
583 # We don't use any of these at present
583 # We don't use any of these at present
584 self.python_line_transforms = []
584 self.python_line_transforms = []
585
585
586 @property
586 @property
587 def transforms(self):
587 def transforms(self):
588 "Quick access to all transformers."
588 "Quick access to all transformers."
589 return self.physical_line_transforms + \
589 return self.physical_line_transforms + \
590 [self.assemble_logical_lines] + self.logical_line_transforms + \
590 [self.assemble_logical_lines] + self.logical_line_transforms + \
591 [self.assemble_python_lines] + self.python_line_transforms
591 [self.assemble_python_lines] + self.python_line_transforms
592
592
593 @property
593 @property
594 def transforms_in_use(self):
594 def transforms_in_use(self):
595 """Transformers, excluding logical line transformers if we're in a
595 """Transformers, excluding logical line transformers if we're in a
596 Python line."""
596 Python line."""
597 t = self.physical_line_transforms[:]
597 t = self.physical_line_transforms[:]
598 if not self.within_python_line:
598 if not self.within_python_line:
599 t += [self.assemble_logical_lines] + self.logical_line_transforms
599 t += [self.assemble_logical_lines] + self.logical_line_transforms
600 return t + [self.assemble_python_lines] + self.python_line_transforms
600 return t + [self.assemble_python_lines] + self.python_line_transforms
601
601
602 def reset(self):
602 def reset(self):
603 """Reset the input buffer and associated state."""
603 """Reset the input buffer and associated state."""
604 super(IPythonInputSplitter, self).reset()
604 super(IPythonInputSplitter, self).reset()
605 self._buffer_raw[:] = []
605 self._buffer_raw[:] = []
606 self.source_raw = ''
606 self.source_raw = ''
607 self.transformer_accumulating = False
607 self.transformer_accumulating = False
608 self.within_python_line = False
608 self.within_python_line = False
609
609
610 for t in self.transforms:
610 for t in self.transforms:
611 try:
611 try:
612 t.reset()
612 t.reset()
613 except SyntaxError:
613 except SyntaxError:
614 # Nothing that calls reset() expects to handle transformer
614 # Nothing that calls reset() expects to handle transformer
615 # errors
615 # errors
616 pass
616 pass
617
617
618 def flush_transformers(self):
618 def flush_transformers(self):
619 def _flush(transform, outs):
619 def _flush(transform, outs):
620 """yield transformed lines
620 """yield transformed lines
621
621
622 always strings, never None
622 always strings, never None
623
623
624 transform: the current transform
624 transform: the current transform
625 outs: an iterable of previously transformed inputs.
625 outs: an iterable of previously transformed inputs.
626 Each may be multiline, which will be passed
626 Each may be multiline, which will be passed
627 one line at a time to transform.
627 one line at a time to transform.
628 """
628 """
629 for out in outs:
629 for out in outs:
630 for line in out.splitlines():
630 for line in out.splitlines():
631 # push one line at a time
631 # push one line at a time
632 tmp = transform.push(line)
632 tmp = transform.push(line)
633 if tmp is not None:
633 if tmp is not None:
634 yield tmp
634 yield tmp
635
635
636 # reset the transform
636 # reset the transform
637 tmp = transform.reset()
637 tmp = transform.reset()
638 if tmp is not None:
638 if tmp is not None:
639 yield tmp
639 yield tmp
640
640
641 out = []
641 out = []
642 for t in self.transforms_in_use:
642 for t in self.transforms_in_use:
643 out = _flush(t, out)
643 out = _flush(t, out)
644
644
645 out = list(out)
645 out = list(out)
646 if out:
646 if out:
647 self._store('\n'.join(out))
647 self._store('\n'.join(out))
648
648
649 def raw_reset(self):
649 def raw_reset(self):
650 """Return raw input only and perform a full reset.
650 """Return raw input only and perform a full reset.
651 """
651 """
652 out = self.source_raw
652 out = self.source_raw
653 self.reset()
653 self.reset()
654 return out
654 return out
655
655
656 def source_reset(self):
656 def source_reset(self):
657 try:
657 try:
658 self.flush_transformers()
658 self.flush_transformers()
659 return self.source
659 return self.source
660 finally:
660 finally:
661 self.reset()
661 self.reset()
662
662
663 def push_accepts_more(self):
663 def push_accepts_more(self):
664 if self.transformer_accumulating:
664 if self.transformer_accumulating:
665 return True
665 return True
666 else:
666 else:
667 return super(IPythonInputSplitter, self).push_accepts_more()
667 return super(IPythonInputSplitter, self).push_accepts_more()
668
668
669 def transform_cell(self, cell):
669 def transform_cell(self, cell):
670 """Process and translate a cell of input.
670 """Process and translate a cell of input.
671 """
671 """
672 self.reset()
672 self.reset()
673 try:
673 try:
674 self.push(cell)
674 self.push(cell)
675 self.flush_transformers()
675 self.flush_transformers()
676 return self.source
676 return self.source
677 finally:
677 finally:
678 self.reset()
678 self.reset()
679
679
680 def push(self, lines):
680 def push(self, lines):
681 """Push one or more lines of IPython input.
681 """Push one or more lines of IPython input.
682
682
683 This stores the given lines and returns a status code indicating
683 This stores the given lines and returns a status code indicating
684 whether the code forms a complete Python block or not, after processing
684 whether the code forms a complete Python block or not, after processing
685 all input lines for special IPython syntax.
685 all input lines for special IPython syntax.
686
686
687 Any exceptions generated in compilation are swallowed, but if an
687 Any exceptions generated in compilation are swallowed, but if an
688 exception was produced, the method returns True.
688 exception was produced, the method returns True.
689
689
690 Parameters
690 Parameters
691 ----------
691 ----------
692 lines : string
692 lines : string
693 One or more lines of Python input.
693 One or more lines of Python input.
694
694
695 Returns
695 Returns
696 -------
696 -------
697 is_complete : boolean
697 is_complete : boolean
698 True if the current input source (the result of the current input
698 True if the current input source (the result of the current input
699 plus prior inputs) forms a complete Python execution block. Note that
699 plus prior inputs) forms a complete Python execution block. Note that
700 this value is also stored as a private attribute (_is_complete), so it
700 this value is also stored as a private attribute (_is_complete), so it
701 can be queried at any time.
701 can be queried at any time.
702 """
702 """
703
703
704 # We must ensure all input is pure unicode
704 # We must ensure all input is pure unicode
705 lines = cast_unicode(lines, self.encoding)
705 lines = cast_unicode(lines, self.encoding)
706 # ''.splitlines() --> [], but we need to push the empty line to transformers
706 # ''.splitlines() --> [], but we need to push the empty line to transformers
707 lines_list = lines.splitlines()
707 lines_list = lines.splitlines()
708 if not lines_list:
708 if not lines_list:
709 lines_list = ['']
709 lines_list = ['']
710
710
711 # Store raw source before applying any transformations to it. Note
711 # Store raw source before applying any transformations to it. Note
712 # that this must be done *after* the reset() call that would otherwise
712 # that this must be done *after* the reset() call that would otherwise
713 # flush the buffer.
713 # flush the buffer.
714 self._store(lines, self._buffer_raw, 'source_raw')
714 self._store(lines, self._buffer_raw, 'source_raw')
715
715
716 transformed_lines_list = []
716 transformed_lines_list = []
717 for line in lines_list:
717 for line in lines_list:
718 transformed = self._transform_line(line)
718 transformed = self._transform_line(line)
719 if transformed is not None:
719 if transformed is not None:
720 transformed_lines_list.append(transformed)
720 transformed_lines_list.append(transformed)
721
721
722 if transformed_lines_list:
722 if transformed_lines_list:
723 transformed_lines = '\n'.join(transformed_lines_list)
723 transformed_lines = '\n'.join(transformed_lines_list)
724 return super(IPythonInputSplitter, self).push(transformed_lines)
724 return super(IPythonInputSplitter, self).push(transformed_lines)
725 else:
725 else:
726 # Got nothing back from transformers - they must be waiting for
726 # Got nothing back from transformers - they must be waiting for
727 # more input.
727 # more input.
728 return False
728 return False
729
729
730 def _transform_line(self, line):
730 def _transform_line(self, line):
731 """Push a line of input code through the various transformers.
731 """Push a line of input code through the various transformers.
732
732
733 Returns any output from the transformers, or None if a transformer
733 Returns any output from the transformers, or None if a transformer
734 is accumulating lines.
734 is accumulating lines.
735
735
736 Sets self.transformer_accumulating as a side effect.
736 Sets self.transformer_accumulating as a side effect.
737 """
737 """
738 def _accumulating(dbg):
738 def _accumulating(dbg):
739 #print(dbg)
739 #print(dbg)
740 self.transformer_accumulating = True
740 self.transformer_accumulating = True
741 return None
741 return None
742
742
743 for transformer in self.physical_line_transforms:
743 for transformer in self.physical_line_transforms:
744 line = transformer.push(line)
744 line = transformer.push(line)
745 if line is None:
745 if line is None:
746 return _accumulating(transformer)
746 return _accumulating(transformer)
747
747
748 if not self.within_python_line:
748 if not self.within_python_line:
749 line = self.assemble_logical_lines.push(line)
749 line = self.assemble_logical_lines.push(line)
750 if line is None:
750 if line is None:
751 return _accumulating('acc logical line')
751 return _accumulating('acc logical line')
752
752
753 for transformer in self.logical_line_transforms:
753 for transformer in self.logical_line_transforms:
754 line = transformer.push(line)
754 line = transformer.push(line)
755 if line is None:
755 if line is None:
756 return _accumulating(transformer)
756 return _accumulating(transformer)
757
757
758 line = self.assemble_python_lines.push(line)
758 line = self.assemble_python_lines.push(line)
759 if line is None:
759 if line is None:
760 self.within_python_line = True
760 self.within_python_line = True
761 return _accumulating('acc python line')
761 return _accumulating('acc python line')
762 else:
762 else:
763 self.within_python_line = False
763 self.within_python_line = False
764
764
765 for transformer in self.python_line_transforms:
765 for transformer in self.python_line_transforms:
766 line = transformer.push(line)
766 line = transformer.push(line)
767 if line is None:
767 if line is None:
768 return _accumulating(transformer)
768 return _accumulating(transformer)
769
769
770 #print("transformers clear") #debug
770 #print("transformers clear") #debug
771 self.transformer_accumulating = False
771 self.transformer_accumulating = False
772 return line
772 return line
773
773
@@ -1,536 +1,536 b''
1 """DEPRECATED: Input transformer classes to support IPython special syntax.
1 """DEPRECATED: Input transformer classes to support IPython special syntax.
2
2
3 This module was deprecated in IPython 7.0, in favour of inputtransformer2.
3 This module was deprecated in IPython 7.0, in favour of inputtransformer2.
4
4
5 This includes the machinery to recognise and transform ``%magic`` commands,
5 This includes the machinery to recognise and transform ``%magic`` commands,
6 ``!system`` commands, ``help?`` querying, prompt stripping, and so forth.
6 ``!system`` commands, ``help?`` querying, prompt stripping, and so forth.
7 """
7 """
8 import abc
8 import abc
9 import functools
9 import functools
10 import re
10 import re
11 import tokenize
11 import tokenize
12 from tokenize import generate_tokens, untokenize, TokenError
12 from tokenize import generate_tokens, untokenize, TokenError
13 from io import StringIO
13 from io import StringIO
14
14
15 from IPython.core.splitinput import LineInfo
15 from IPython.core.splitinput import LineInfo
16
16
17 #-----------------------------------------------------------------------------
17 #-----------------------------------------------------------------------------
18 # Globals
18 # Globals
19 #-----------------------------------------------------------------------------
19 #-----------------------------------------------------------------------------
20
20
21 # The escape sequences that define the syntax transformations IPython will
21 # The escape sequences that define the syntax transformations IPython will
22 # apply to user input. These can NOT be just changed here: many regular
22 # apply to user input. These can NOT be just changed here: many regular
23 # expressions and other parts of the code may use their hardcoded values, and
23 # expressions and other parts of the code may use their hardcoded values, and
24 # for all intents and purposes they constitute the 'IPython syntax', so they
24 # for all intents and purposes they constitute the 'IPython syntax', so they
25 # should be considered fixed.
25 # should be considered fixed.
26
26
27 ESC_SHELL = '!' # Send line to underlying system shell
27 ESC_SHELL = '!' # Send line to underlying system shell
28 ESC_SH_CAP = '!!' # Send line to system shell and capture output
28 ESC_SH_CAP = '!!' # Send line to system shell and capture output
29 ESC_HELP = '?' # Find information about object
29 ESC_HELP = '?' # Find information about object
30 ESC_HELP2 = '??' # Find extra-detailed information about object
30 ESC_HELP2 = '??' # Find extra-detailed information about object
31 ESC_MAGIC = '%' # Call magic function
31 ESC_MAGIC = '%' # Call magic function
32 ESC_MAGIC2 = '%%' # Call cell-magic function
32 ESC_MAGIC2 = '%%' # Call cell-magic function
33 ESC_QUOTE = ',' # Split args on whitespace, quote each as string and call
33 ESC_QUOTE = ',' # Split args on whitespace, quote each as string and call
34 ESC_QUOTE2 = ';' # Quote all args as a single string, call
34 ESC_QUOTE2 = ';' # Quote all args as a single string, call
35 ESC_PAREN = '/' # Call first argument with rest of line as arguments
35 ESC_PAREN = '/' # Call first argument with rest of line as arguments
36
36
37 ESC_SEQUENCES = [ESC_SHELL, ESC_SH_CAP, ESC_HELP ,\
37 ESC_SEQUENCES = [ESC_SHELL, ESC_SH_CAP, ESC_HELP ,\
38 ESC_HELP2, ESC_MAGIC, ESC_MAGIC2,\
38 ESC_HELP2, ESC_MAGIC, ESC_MAGIC2,\
39 ESC_QUOTE, ESC_QUOTE2, ESC_PAREN ]
39 ESC_QUOTE, ESC_QUOTE2, ESC_PAREN ]
40
40
41
41
42 class InputTransformer(metaclass=abc.ABCMeta):
42 class InputTransformer(metaclass=abc.ABCMeta):
43 """Abstract base class for line-based input transformers."""
43 """Abstract base class for line-based input transformers."""
44
44
45 @abc.abstractmethod
45 @abc.abstractmethod
46 def push(self, line):
46 def push(self, line):
47 """Send a line of input to the transformer, returning the transformed
47 """Send a line of input to the transformer, returning the transformed
48 input or None if the transformer is waiting for more input.
48 input or None if the transformer is waiting for more input.
49
49
50 Must be overridden by subclasses.
50 Must be overridden by subclasses.
51
51
52 Implementations may raise ``SyntaxError`` if the input is invalid. No
52 Implementations may raise ``SyntaxError`` if the input is invalid. No
53 other exceptions may be raised.
53 other exceptions may be raised.
54 """
54 """
55 pass
55 pass
56
56
57 @abc.abstractmethod
57 @abc.abstractmethod
58 def reset(self):
58 def reset(self):
59 """Return, transformed any lines that the transformer has accumulated,
59 """Return, transformed any lines that the transformer has accumulated,
60 and reset its internal state.
60 and reset its internal state.
61
61
62 Must be overridden by subclasses.
62 Must be overridden by subclasses.
63 """
63 """
64 pass
64 pass
65
65
66 @classmethod
66 @classmethod
67 def wrap(cls, func):
67 def wrap(cls, func):
68 """Can be used by subclasses as a decorator, to return a factory that
68 """Can be used by subclasses as a decorator, to return a factory that
69 will allow instantiation with the decorated object.
69 will allow instantiation with the decorated object.
70 """
70 """
71 @functools.wraps(func)
71 @functools.wraps(func)
72 def transformer_factory(**kwargs):
72 def transformer_factory(**kwargs):
73 return cls(func, **kwargs)
73 return cls(func, **kwargs)
74
74
75 return transformer_factory
75 return transformer_factory
76
76
77 class StatelessInputTransformer(InputTransformer):
77 class StatelessInputTransformer(InputTransformer):
78 """Wrapper for a stateless input transformer implemented as a function."""
78 """Wrapper for a stateless input transformer implemented as a function."""
79 def __init__(self, func):
79 def __init__(self, func):
80 self.func = func
80 self.func = func
81
81
82 def __repr__(self):
82 def __repr__(self):
83 return "StatelessInputTransformer(func={0!r})".format(self.func)
83 return "StatelessInputTransformer(func={0!r})".format(self.func)
84
84
85 def push(self, line):
85 def push(self, line):
86 """Send a line of input to the transformer, returning the
86 """Send a line of input to the transformer, returning the
87 transformed input."""
87 transformed input."""
88 return self.func(line)
88 return self.func(line)
89
89
90 def reset(self):
90 def reset(self):
91 """No-op - exists for compatibility."""
91 """No-op - exists for compatibility."""
92 pass
92 pass
93
93
94 class CoroutineInputTransformer(InputTransformer):
94 class CoroutineInputTransformer(InputTransformer):
95 """Wrapper for an input transformer implemented as a coroutine."""
95 """Wrapper for an input transformer implemented as a coroutine."""
96 def __init__(self, coro, **kwargs):
96 def __init__(self, coro, **kwargs):
97 # Prime it
97 # Prime it
98 self.coro = coro(**kwargs)
98 self.coro = coro(**kwargs)
99 next(self.coro)
99 next(self.coro)
100
100
101 def __repr__(self):
101 def __repr__(self):
102 return "CoroutineInputTransformer(coro={0!r})".format(self.coro)
102 return "CoroutineInputTransformer(coro={0!r})".format(self.coro)
103
103
104 def push(self, line):
104 def push(self, line):
105 """Send a line of input to the transformer, returning the
105 """Send a line of input to the transformer, returning the
106 transformed input or None if the transformer is waiting for more
106 transformed input or None if the transformer is waiting for more
107 input.
107 input.
108 """
108 """
109 return self.coro.send(line)
109 return self.coro.send(line)
110
110
111 def reset(self):
111 def reset(self):
112 """Return, transformed any lines that the transformer has
112 """Return, transformed any lines that the transformer has
113 accumulated, and reset its internal state.
113 accumulated, and reset its internal state.
114 """
114 """
115 return self.coro.send(None)
115 return self.coro.send(None)
116
116
117 class TokenInputTransformer(InputTransformer):
117 class TokenInputTransformer(InputTransformer):
118 """Wrapper for a token-based input transformer.
118 """Wrapper for a token-based input transformer.
119
119
120 func should accept a list of tokens (5-tuples, see tokenize docs), and
120 func should accept a list of tokens (5-tuples, see tokenize docs), and
121 return an iterable which can be passed to tokenize.untokenize().
121 return an iterable which can be passed to tokenize.untokenize().
122 """
122 """
123 def __init__(self, func):
123 def __init__(self, func):
124 self.func = func
124 self.func = func
125 self.buf = []
125 self.buf = []
126 self.reset_tokenizer()
126 self.reset_tokenizer()
127
127
128 def reset_tokenizer(self):
128 def reset_tokenizer(self):
129 it = iter(self.buf)
129 it = iter(self.buf)
130 self.tokenizer = generate_tokens(it.__next__)
130 self.tokenizer = generate_tokens(it.__next__)
131
131
132 def push(self, line):
132 def push(self, line):
133 self.buf.append(line + '\n')
133 self.buf.append(line + '\n')
134 if all(l.isspace() for l in self.buf):
134 if all(l.isspace() for l in self.buf):
135 return self.reset()
135 return self.reset()
136
136
137 tokens = []
137 tokens = []
138 stop_at_NL = False
138 stop_at_NL = False
139 try:
139 try:
140 for intok in self.tokenizer:
140 for intok in self.tokenizer:
141 tokens.append(intok)
141 tokens.append(intok)
142 t = intok[0]
142 t = intok[0]
143 if t == tokenize.NEWLINE or (stop_at_NL and t == tokenize.NL):
143 if t == tokenize.NEWLINE or (stop_at_NL and t == tokenize.NL):
144 # Stop before we try to pull a line we don't have yet
144 # Stop before we try to pull a line we don't have yet
145 break
145 break
146 elif t == tokenize.ERRORTOKEN:
146 elif t == tokenize.ERRORTOKEN:
147 stop_at_NL = True
147 stop_at_NL = True
148 except TokenError:
148 except TokenError:
149 # Multi-line statement - stop and try again with the next line
149 # Multi-line statement - stop and try again with the next line
150 self.reset_tokenizer()
150 self.reset_tokenizer()
151 return None
151 return None
152
152
153 return self.output(tokens)
153 return self.output(tokens)
154
154
155 def output(self, tokens):
155 def output(self, tokens):
156 self.buf.clear()
156 self.buf.clear()
157 self.reset_tokenizer()
157 self.reset_tokenizer()
158 return untokenize(self.func(tokens)).rstrip('\n')
158 return untokenize(self.func(tokens)).rstrip('\n')
159
159
160 def reset(self):
160 def reset(self):
161 l = ''.join(self.buf)
161 l = ''.join(self.buf)
162 self.buf.clear()
162 self.buf.clear()
163 self.reset_tokenizer()
163 self.reset_tokenizer()
164 if l:
164 if l:
165 return l.rstrip('\n')
165 return l.rstrip('\n')
166
166
167 class assemble_python_lines(TokenInputTransformer):
167 class assemble_python_lines(TokenInputTransformer):
168 def __init__(self):
168 def __init__(self):
169 super(assemble_python_lines, self).__init__(None)
169 super(assemble_python_lines, self).__init__(None)
170
170
171 def output(self, tokens):
171 def output(self, tokens):
172 return self.reset()
172 return self.reset()
173
173
174 @CoroutineInputTransformer.wrap
174 @CoroutineInputTransformer.wrap
175 def assemble_logical_lines():
175 def assemble_logical_lines():
176 """Join lines following explicit line continuations (\)"""
176 r"""Join lines following explicit line continuations (\)"""
177 line = ''
177 line = ''
178 while True:
178 while True:
179 line = (yield line)
179 line = (yield line)
180 if not line or line.isspace():
180 if not line or line.isspace():
181 continue
181 continue
182
182
183 parts = []
183 parts = []
184 while line is not None:
184 while line is not None:
185 if line.endswith('\\') and (not has_comment(line)):
185 if line.endswith('\\') and (not has_comment(line)):
186 parts.append(line[:-1])
186 parts.append(line[:-1])
187 line = (yield None) # Get another line
187 line = (yield None) # Get another line
188 else:
188 else:
189 parts.append(line)
189 parts.append(line)
190 break
190 break
191
191
192 # Output
192 # Output
193 line = ''.join(parts)
193 line = ''.join(parts)
194
194
195 # Utilities
195 # Utilities
196 def _make_help_call(target, esc, lspace, next_input=None):
196 def _make_help_call(target, esc, lspace, next_input=None):
197 """Prepares a pinfo(2)/psearch call from a target name and the escape
197 """Prepares a pinfo(2)/psearch call from a target name and the escape
198 (i.e. ? or ??)"""
198 (i.e. ? or ??)"""
199 method = 'pinfo2' if esc == '??' \
199 method = 'pinfo2' if esc == '??' \
200 else 'psearch' if '*' in target \
200 else 'psearch' if '*' in target \
201 else 'pinfo'
201 else 'pinfo'
202 arg = " ".join([method, target])
202 arg = " ".join([method, target])
203 #Prepare arguments for get_ipython().run_line_magic(magic_name, magic_args)
203 #Prepare arguments for get_ipython().run_line_magic(magic_name, magic_args)
204 t_magic_name, _, t_magic_arg_s = arg.partition(' ')
204 t_magic_name, _, t_magic_arg_s = arg.partition(' ')
205 t_magic_name = t_magic_name.lstrip(ESC_MAGIC)
205 t_magic_name = t_magic_name.lstrip(ESC_MAGIC)
206 if next_input is None:
206 if next_input is None:
207 return '%sget_ipython().run_line_magic(%r, %r)' % (lspace, t_magic_name, t_magic_arg_s)
207 return '%sget_ipython().run_line_magic(%r, %r)' % (lspace, t_magic_name, t_magic_arg_s)
208 else:
208 else:
209 return '%sget_ipython().set_next_input(%r);get_ipython().run_line_magic(%r, %r)' % \
209 return '%sget_ipython().set_next_input(%r);get_ipython().run_line_magic(%r, %r)' % \
210 (lspace, next_input, t_magic_name, t_magic_arg_s)
210 (lspace, next_input, t_magic_name, t_magic_arg_s)
211
211
212 # These define the transformations for the different escape characters.
212 # These define the transformations for the different escape characters.
213 def _tr_system(line_info):
213 def _tr_system(line_info):
214 "Translate lines escaped with: !"
214 "Translate lines escaped with: !"
215 cmd = line_info.line.lstrip().lstrip(ESC_SHELL)
215 cmd = line_info.line.lstrip().lstrip(ESC_SHELL)
216 return '%sget_ipython().system(%r)' % (line_info.pre, cmd)
216 return '%sget_ipython().system(%r)' % (line_info.pre, cmd)
217
217
218 def _tr_system2(line_info):
218 def _tr_system2(line_info):
219 "Translate lines escaped with: !!"
219 "Translate lines escaped with: !!"
220 cmd = line_info.line.lstrip()[2:]
220 cmd = line_info.line.lstrip()[2:]
221 return '%sget_ipython().getoutput(%r)' % (line_info.pre, cmd)
221 return '%sget_ipython().getoutput(%r)' % (line_info.pre, cmd)
222
222
223 def _tr_help(line_info):
223 def _tr_help(line_info):
224 "Translate lines escaped with: ?/??"
224 "Translate lines escaped with: ?/??"
225 # A naked help line should just fire the intro help screen
225 # A naked help line should just fire the intro help screen
226 if not line_info.line[1:]:
226 if not line_info.line[1:]:
227 return 'get_ipython().show_usage()'
227 return 'get_ipython().show_usage()'
228
228
229 return _make_help_call(line_info.ifun, line_info.esc, line_info.pre)
229 return _make_help_call(line_info.ifun, line_info.esc, line_info.pre)
230
230
231 def _tr_magic(line_info):
231 def _tr_magic(line_info):
232 "Translate lines escaped with: %"
232 "Translate lines escaped with: %"
233 tpl = '%sget_ipython().run_line_magic(%r, %r)'
233 tpl = '%sget_ipython().run_line_magic(%r, %r)'
234 if line_info.line.startswith(ESC_MAGIC2):
234 if line_info.line.startswith(ESC_MAGIC2):
235 return line_info.line
235 return line_info.line
236 cmd = ' '.join([line_info.ifun, line_info.the_rest]).strip()
236 cmd = ' '.join([line_info.ifun, line_info.the_rest]).strip()
237 #Prepare arguments for get_ipython().run_line_magic(magic_name, magic_args)
237 #Prepare arguments for get_ipython().run_line_magic(magic_name, magic_args)
238 t_magic_name, _, t_magic_arg_s = cmd.partition(' ')
238 t_magic_name, _, t_magic_arg_s = cmd.partition(' ')
239 t_magic_name = t_magic_name.lstrip(ESC_MAGIC)
239 t_magic_name = t_magic_name.lstrip(ESC_MAGIC)
240 return tpl % (line_info.pre, t_magic_name, t_magic_arg_s)
240 return tpl % (line_info.pre, t_magic_name, t_magic_arg_s)
241
241
242 def _tr_quote(line_info):
242 def _tr_quote(line_info):
243 "Translate lines escaped with: ,"
243 "Translate lines escaped with: ,"
244 return '%s%s("%s")' % (line_info.pre, line_info.ifun,
244 return '%s%s("%s")' % (line_info.pre, line_info.ifun,
245 '", "'.join(line_info.the_rest.split()) )
245 '", "'.join(line_info.the_rest.split()) )
246
246
247 def _tr_quote2(line_info):
247 def _tr_quote2(line_info):
248 "Translate lines escaped with: ;"
248 "Translate lines escaped with: ;"
249 return '%s%s("%s")' % (line_info.pre, line_info.ifun,
249 return '%s%s("%s")' % (line_info.pre, line_info.ifun,
250 line_info.the_rest)
250 line_info.the_rest)
251
251
252 def _tr_paren(line_info):
252 def _tr_paren(line_info):
253 "Translate lines escaped with: /"
253 "Translate lines escaped with: /"
254 return '%s%s(%s)' % (line_info.pre, line_info.ifun,
254 return '%s%s(%s)' % (line_info.pre, line_info.ifun,
255 ", ".join(line_info.the_rest.split()))
255 ", ".join(line_info.the_rest.split()))
256
256
257 tr = { ESC_SHELL : _tr_system,
257 tr = { ESC_SHELL : _tr_system,
258 ESC_SH_CAP : _tr_system2,
258 ESC_SH_CAP : _tr_system2,
259 ESC_HELP : _tr_help,
259 ESC_HELP : _tr_help,
260 ESC_HELP2 : _tr_help,
260 ESC_HELP2 : _tr_help,
261 ESC_MAGIC : _tr_magic,
261 ESC_MAGIC : _tr_magic,
262 ESC_QUOTE : _tr_quote,
262 ESC_QUOTE : _tr_quote,
263 ESC_QUOTE2 : _tr_quote2,
263 ESC_QUOTE2 : _tr_quote2,
264 ESC_PAREN : _tr_paren }
264 ESC_PAREN : _tr_paren }
265
265
266 @StatelessInputTransformer.wrap
266 @StatelessInputTransformer.wrap
267 def escaped_commands(line):
267 def escaped_commands(line):
268 """Transform escaped commands - %magic, !system, ?help + various autocalls.
268 """Transform escaped commands - %magic, !system, ?help + various autocalls.
269 """
269 """
270 if not line or line.isspace():
270 if not line or line.isspace():
271 return line
271 return line
272 lineinf = LineInfo(line)
272 lineinf = LineInfo(line)
273 if lineinf.esc not in tr:
273 if lineinf.esc not in tr:
274 return line
274 return line
275
275
276 return tr[lineinf.esc](lineinf)
276 return tr[lineinf.esc](lineinf)
277
277
278 _initial_space_re = re.compile(r'\s*')
278 _initial_space_re = re.compile(r'\s*')
279
279
280 _help_end_re = re.compile(r"""(%{0,2}
280 _help_end_re = re.compile(r"""(%{0,2}
281 [a-zA-Z_*][\w*]* # Variable name
281 [a-zA-Z_*][\w*]* # Variable name
282 (\.[a-zA-Z_*][\w*]*)* # .etc.etc
282 (\.[a-zA-Z_*][\w*]*)* # .etc.etc
283 )
283 )
284 (\?\??)$ # ? or ??
284 (\?\??)$ # ? or ??
285 """,
285 """,
286 re.VERBOSE)
286 re.VERBOSE)
287
287
288 # Extra pseudotokens for multiline strings and data structures
288 # Extra pseudotokens for multiline strings and data structures
289 _MULTILINE_STRING = object()
289 _MULTILINE_STRING = object()
290 _MULTILINE_STRUCTURE = object()
290 _MULTILINE_STRUCTURE = object()
291
291
292 def _line_tokens(line):
292 def _line_tokens(line):
293 """Helper for has_comment and ends_in_comment_or_string."""
293 """Helper for has_comment and ends_in_comment_or_string."""
294 readline = StringIO(line).readline
294 readline = StringIO(line).readline
295 toktypes = set()
295 toktypes = set()
296 try:
296 try:
297 for t in generate_tokens(readline):
297 for t in generate_tokens(readline):
298 toktypes.add(t[0])
298 toktypes.add(t[0])
299 except TokenError as e:
299 except TokenError as e:
300 # There are only two cases where a TokenError is raised.
300 # There are only two cases where a TokenError is raised.
301 if 'multi-line string' in e.args[0]:
301 if 'multi-line string' in e.args[0]:
302 toktypes.add(_MULTILINE_STRING)
302 toktypes.add(_MULTILINE_STRING)
303 else:
303 else:
304 toktypes.add(_MULTILINE_STRUCTURE)
304 toktypes.add(_MULTILINE_STRUCTURE)
305 return toktypes
305 return toktypes
306
306
307 def has_comment(src):
307 def has_comment(src):
308 """Indicate whether an input line has (i.e. ends in, or is) a comment.
308 """Indicate whether an input line has (i.e. ends in, or is) a comment.
309
309
310 This uses tokenize, so it can distinguish comments from # inside strings.
310 This uses tokenize, so it can distinguish comments from # inside strings.
311
311
312 Parameters
312 Parameters
313 ----------
313 ----------
314 src : string
314 src : string
315 A single line input string.
315 A single line input string.
316
316
317 Returns
317 Returns
318 -------
318 -------
319 comment : bool
319 comment : bool
320 True if source has a comment.
320 True if source has a comment.
321 """
321 """
322 return (tokenize.COMMENT in _line_tokens(src))
322 return (tokenize.COMMENT in _line_tokens(src))
323
323
324 def ends_in_comment_or_string(src):
324 def ends_in_comment_or_string(src):
325 """Indicates whether or not an input line ends in a comment or within
325 """Indicates whether or not an input line ends in a comment or within
326 a multiline string.
326 a multiline string.
327
327
328 Parameters
328 Parameters
329 ----------
329 ----------
330 src : string
330 src : string
331 A single line input string.
331 A single line input string.
332
332
333 Returns
333 Returns
334 -------
334 -------
335 comment : bool
335 comment : bool
336 True if source ends in a comment or multiline string.
336 True if source ends in a comment or multiline string.
337 """
337 """
338 toktypes = _line_tokens(src)
338 toktypes = _line_tokens(src)
339 return (tokenize.COMMENT in toktypes) or (_MULTILINE_STRING in toktypes)
339 return (tokenize.COMMENT in toktypes) or (_MULTILINE_STRING in toktypes)
340
340
341
341
342 @StatelessInputTransformer.wrap
342 @StatelessInputTransformer.wrap
343 def help_end(line):
343 def help_end(line):
344 """Translate lines with ?/?? at the end"""
344 """Translate lines with ?/?? at the end"""
345 m = _help_end_re.search(line)
345 m = _help_end_re.search(line)
346 if m is None or ends_in_comment_or_string(line):
346 if m is None or ends_in_comment_or_string(line):
347 return line
347 return line
348 target = m.group(1)
348 target = m.group(1)
349 esc = m.group(3)
349 esc = m.group(3)
350 lspace = _initial_space_re.match(line).group(0)
350 lspace = _initial_space_re.match(line).group(0)
351
351
352 # If we're mid-command, put it back on the next prompt for the user.
352 # If we're mid-command, put it back on the next prompt for the user.
353 next_input = line.rstrip('?') if line.strip() != m.group(0) else None
353 next_input = line.rstrip('?') if line.strip() != m.group(0) else None
354
354
355 return _make_help_call(target, esc, lspace, next_input)
355 return _make_help_call(target, esc, lspace, next_input)
356
356
357
357
358 @CoroutineInputTransformer.wrap
358 @CoroutineInputTransformer.wrap
359 def cellmagic(end_on_blank_line=False):
359 def cellmagic(end_on_blank_line=False):
360 """Captures & transforms cell magics.
360 """Captures & transforms cell magics.
361
361
362 After a cell magic is started, this stores up any lines it gets until it is
362 After a cell magic is started, this stores up any lines it gets until it is
363 reset (sent None).
363 reset (sent None).
364 """
364 """
365 tpl = 'get_ipython().run_cell_magic(%r, %r, %r)'
365 tpl = 'get_ipython().run_cell_magic(%r, %r, %r)'
366 cellmagic_help_re = re.compile('%%\w+\?')
366 cellmagic_help_re = re.compile(r'%%\w+\?')
367 line = ''
367 line = ''
368 while True:
368 while True:
369 line = (yield line)
369 line = (yield line)
370 # consume leading empty lines
370 # consume leading empty lines
371 while not line:
371 while not line:
372 line = (yield line)
372 line = (yield line)
373
373
374 if not line.startswith(ESC_MAGIC2):
374 if not line.startswith(ESC_MAGIC2):
375 # This isn't a cell magic, idle waiting for reset then start over
375 # This isn't a cell magic, idle waiting for reset then start over
376 while line is not None:
376 while line is not None:
377 line = (yield line)
377 line = (yield line)
378 continue
378 continue
379
379
380 if cellmagic_help_re.match(line):
380 if cellmagic_help_re.match(line):
381 # This case will be handled by help_end
381 # This case will be handled by help_end
382 continue
382 continue
383
383
384 first = line
384 first = line
385 body = []
385 body = []
386 line = (yield None)
386 line = (yield None)
387 while (line is not None) and \
387 while (line is not None) and \
388 ((line.strip() != '') or not end_on_blank_line):
388 ((line.strip() != '') or not end_on_blank_line):
389 body.append(line)
389 body.append(line)
390 line = (yield None)
390 line = (yield None)
391
391
392 # Output
392 # Output
393 magic_name, _, first = first.partition(' ')
393 magic_name, _, first = first.partition(' ')
394 magic_name = magic_name.lstrip(ESC_MAGIC2)
394 magic_name = magic_name.lstrip(ESC_MAGIC2)
395 line = tpl % (magic_name, first, u'\n'.join(body))
395 line = tpl % (magic_name, first, u'\n'.join(body))
396
396
397
397
398 def _strip_prompts(prompt_re, initial_re=None, turnoff_re=None):
398 def _strip_prompts(prompt_re, initial_re=None, turnoff_re=None):
399 """Remove matching input prompts from a block of input.
399 """Remove matching input prompts from a block of input.
400
400
401 Parameters
401 Parameters
402 ----------
402 ----------
403 prompt_re : regular expression
403 prompt_re : regular expression
404 A regular expression matching any input prompt (including continuation)
404 A regular expression matching any input prompt (including continuation)
405 initial_re : regular expression, optional
405 initial_re : regular expression, optional
406 A regular expression matching only the initial prompt, but not continuation.
406 A regular expression matching only the initial prompt, but not continuation.
407 If no initial expression is given, prompt_re will be used everywhere.
407 If no initial expression is given, prompt_re will be used everywhere.
408 Used mainly for plain Python prompts, where the continuation prompt
408 Used mainly for plain Python prompts, where the continuation prompt
409 ``...`` is a valid Python expression in Python 3, so shouldn't be stripped.
409 ``...`` is a valid Python expression in Python 3, so shouldn't be stripped.
410
410
411 If initial_re and prompt_re differ,
411 If initial_re and prompt_re differ,
412 only initial_re will be tested against the first line.
412 only initial_re will be tested against the first line.
413 If any prompt is found on the first two lines,
413 If any prompt is found on the first two lines,
414 prompts will be stripped from the rest of the block.
414 prompts will be stripped from the rest of the block.
415 """
415 """
416 if initial_re is None:
416 if initial_re is None:
417 initial_re = prompt_re
417 initial_re = prompt_re
418 line = ''
418 line = ''
419 while True:
419 while True:
420 line = (yield line)
420 line = (yield line)
421
421
422 # First line of cell
422 # First line of cell
423 if line is None:
423 if line is None:
424 continue
424 continue
425 out, n1 = initial_re.subn('', line, count=1)
425 out, n1 = initial_re.subn('', line, count=1)
426 if turnoff_re and not n1:
426 if turnoff_re and not n1:
427 if turnoff_re.match(line):
427 if turnoff_re.match(line):
428 # We're in e.g. a cell magic; disable this transformer for
428 # We're in e.g. a cell magic; disable this transformer for
429 # the rest of the cell.
429 # the rest of the cell.
430 while line is not None:
430 while line is not None:
431 line = (yield line)
431 line = (yield line)
432 continue
432 continue
433
433
434 line = (yield out)
434 line = (yield out)
435
435
436 if line is None:
436 if line is None:
437 continue
437 continue
438 # check for any prompt on the second line of the cell,
438 # check for any prompt on the second line of the cell,
439 # because people often copy from just after the first prompt,
439 # because people often copy from just after the first prompt,
440 # so we might not see it in the first line.
440 # so we might not see it in the first line.
441 out, n2 = prompt_re.subn('', line, count=1)
441 out, n2 = prompt_re.subn('', line, count=1)
442 line = (yield out)
442 line = (yield out)
443
443
444 if n1 or n2:
444 if n1 or n2:
445 # Found a prompt in the first two lines - check for it in
445 # Found a prompt in the first two lines - check for it in
446 # the rest of the cell as well.
446 # the rest of the cell as well.
447 while line is not None:
447 while line is not None:
448 line = (yield prompt_re.sub('', line, count=1))
448 line = (yield prompt_re.sub('', line, count=1))
449
449
450 else:
450 else:
451 # Prompts not in input - wait for reset
451 # Prompts not in input - wait for reset
452 while line is not None:
452 while line is not None:
453 line = (yield line)
453 line = (yield line)
454
454
455 @CoroutineInputTransformer.wrap
455 @CoroutineInputTransformer.wrap
456 def classic_prompt():
456 def classic_prompt():
457 """Strip the >>>/... prompts of the Python interactive shell."""
457 """Strip the >>>/... prompts of the Python interactive shell."""
458 # FIXME: non-capturing version (?:...) usable?
458 # FIXME: non-capturing version (?:...) usable?
459 prompt_re = re.compile(r'^(>>>|\.\.\.)( |$)')
459 prompt_re = re.compile(r'^(>>>|\.\.\.)( |$)')
460 initial_re = re.compile(r'^>>>( |$)')
460 initial_re = re.compile(r'^>>>( |$)')
461 # Any %magic/!system is IPython syntax, so we needn't look for >>> prompts
461 # Any %magic/!system is IPython syntax, so we needn't look for >>> prompts
462 turnoff_re = re.compile(r'^[%!]')
462 turnoff_re = re.compile(r'^[%!]')
463 return _strip_prompts(prompt_re, initial_re, turnoff_re)
463 return _strip_prompts(prompt_re, initial_re, turnoff_re)
464
464
465 @CoroutineInputTransformer.wrap
465 @CoroutineInputTransformer.wrap
466 def ipy_prompt():
466 def ipy_prompt():
467 """Strip IPython's In [1]:/...: prompts."""
467 """Strip IPython's In [1]:/...: prompts."""
468 # FIXME: non-capturing version (?:...) usable?
468 # FIXME: non-capturing version (?:...) usable?
469 prompt_re = re.compile(r'^(In \[\d+\]: |\s*\.{3,}: ?)')
469 prompt_re = re.compile(r'^(In \[\d+\]: |\s*\.{3,}: ?)')
470 # Disable prompt stripping inside cell magics
470 # Disable prompt stripping inside cell magics
471 turnoff_re = re.compile(r'^%%')
471 turnoff_re = re.compile(r'^%%')
472 return _strip_prompts(prompt_re, turnoff_re=turnoff_re)
472 return _strip_prompts(prompt_re, turnoff_re=turnoff_re)
473
473
474
474
475 @CoroutineInputTransformer.wrap
475 @CoroutineInputTransformer.wrap
476 def leading_indent():
476 def leading_indent():
477 """Remove leading indentation.
477 """Remove leading indentation.
478
478
479 If the first line starts with a spaces or tabs, the same whitespace will be
479 If the first line starts with a spaces or tabs, the same whitespace will be
480 removed from each following line until it is reset.
480 removed from each following line until it is reset.
481 """
481 """
482 space_re = re.compile(r'^[ \t]+')
482 space_re = re.compile(r'^[ \t]+')
483 line = ''
483 line = ''
484 while True:
484 while True:
485 line = (yield line)
485 line = (yield line)
486
486
487 if line is None:
487 if line is None:
488 continue
488 continue
489
489
490 m = space_re.match(line)
490 m = space_re.match(line)
491 if m:
491 if m:
492 space = m.group(0)
492 space = m.group(0)
493 while line is not None:
493 while line is not None:
494 if line.startswith(space):
494 if line.startswith(space):
495 line = line[len(space):]
495 line = line[len(space):]
496 line = (yield line)
496 line = (yield line)
497 else:
497 else:
498 # No leading spaces - wait for reset
498 # No leading spaces - wait for reset
499 while line is not None:
499 while line is not None:
500 line = (yield line)
500 line = (yield line)
501
501
502
502
503 _assign_pat = \
503 _assign_pat = \
504 r'''(?P<lhs>(\s*)
504 r'''(?P<lhs>(\s*)
505 ([\w\.]+) # Initial identifier
505 ([\w\.]+) # Initial identifier
506 (\s*,\s*
506 (\s*,\s*
507 \*?[\w\.]+)* # Further identifiers for unpacking
507 \*?[\w\.]+)* # Further identifiers for unpacking
508 \s*?,? # Trailing comma
508 \s*?,? # Trailing comma
509 )
509 )
510 \s*=\s*
510 \s*=\s*
511 '''
511 '''
512
512
513 assign_system_re = re.compile(r'{}!\s*(?P<cmd>.*)'.format(_assign_pat), re.VERBOSE)
513 assign_system_re = re.compile(r'{}!\s*(?P<cmd>.*)'.format(_assign_pat), re.VERBOSE)
514 assign_system_template = '%s = get_ipython().getoutput(%r)'
514 assign_system_template = '%s = get_ipython().getoutput(%r)'
515 @StatelessInputTransformer.wrap
515 @StatelessInputTransformer.wrap
516 def assign_from_system(line):
516 def assign_from_system(line):
517 """Transform assignment from system commands (e.g. files = !ls)"""
517 """Transform assignment from system commands (e.g. files = !ls)"""
518 m = assign_system_re.match(line)
518 m = assign_system_re.match(line)
519 if m is None:
519 if m is None:
520 return line
520 return line
521
521
522 return assign_system_template % m.group('lhs', 'cmd')
522 return assign_system_template % m.group('lhs', 'cmd')
523
523
524 assign_magic_re = re.compile(r'{}%\s*(?P<cmd>.*)'.format(_assign_pat), re.VERBOSE)
524 assign_magic_re = re.compile(r'{}%\s*(?P<cmd>.*)'.format(_assign_pat), re.VERBOSE)
525 assign_magic_template = '%s = get_ipython().run_line_magic(%r, %r)'
525 assign_magic_template = '%s = get_ipython().run_line_magic(%r, %r)'
526 @StatelessInputTransformer.wrap
526 @StatelessInputTransformer.wrap
527 def assign_from_magic(line):
527 def assign_from_magic(line):
528 """Transform assignment from magic commands (e.g. a = %who_ls)"""
528 """Transform assignment from magic commands (e.g. a = %who_ls)"""
529 m = assign_magic_re.match(line)
529 m = assign_magic_re.match(line)
530 if m is None:
530 if m is None:
531 return line
531 return line
532 #Prepare arguments for get_ipython().run_line_magic(magic_name, magic_args)
532 #Prepare arguments for get_ipython().run_line_magic(magic_name, magic_args)
533 m_lhs, m_cmd = m.group('lhs', 'cmd')
533 m_lhs, m_cmd = m.group('lhs', 'cmd')
534 t_magic_name, _, t_magic_arg_s = m_cmd.partition(' ')
534 t_magic_name, _, t_magic_arg_s = m_cmd.partition(' ')
535 t_magic_name = t_magic_name.lstrip(ESC_MAGIC)
535 t_magic_name = t_magic_name.lstrip(ESC_MAGIC)
536 return assign_magic_template % (m_lhs, t_magic_name, t_magic_arg_s)
536 return assign_magic_template % (m_lhs, t_magic_name, t_magic_arg_s)
@@ -1,158 +1,158 b''
1 """Implementation of configuration-related magic functions.
1 """Implementation of configuration-related magic functions.
2 """
2 """
3 #-----------------------------------------------------------------------------
3 #-----------------------------------------------------------------------------
4 # Copyright (c) 2012 The IPython Development Team.
4 # Copyright (c) 2012 The IPython Development Team.
5 #
5 #
6 # Distributed under the terms of the Modified BSD License.
6 # Distributed under the terms of the Modified BSD License.
7 #
7 #
8 # The full license is in the file COPYING.txt, distributed with this software.
8 # The full license is in the file COPYING.txt, distributed with this software.
9 #-----------------------------------------------------------------------------
9 #-----------------------------------------------------------------------------
10
10
11 #-----------------------------------------------------------------------------
11 #-----------------------------------------------------------------------------
12 # Imports
12 # Imports
13 #-----------------------------------------------------------------------------
13 #-----------------------------------------------------------------------------
14
14
15 # Stdlib
15 # Stdlib
16 import re
16 import re
17
17
18 # Our own packages
18 # Our own packages
19 from IPython.core.error import UsageError
19 from IPython.core.error import UsageError
20 from IPython.core.magic import Magics, magics_class, line_magic
20 from IPython.core.magic import Magics, magics_class, line_magic
21 from logging import error
21 from logging import error
22
22
23 #-----------------------------------------------------------------------------
23 #-----------------------------------------------------------------------------
24 # Magic implementation classes
24 # Magic implementation classes
25 #-----------------------------------------------------------------------------
25 #-----------------------------------------------------------------------------
26
26
27 reg = re.compile('^\w+\.\w+$')
27 reg = re.compile(r'^\w+\.\w+$')
28 @magics_class
28 @magics_class
29 class ConfigMagics(Magics):
29 class ConfigMagics(Magics):
30
30
31 def __init__(self, shell):
31 def __init__(self, shell):
32 super(ConfigMagics, self).__init__(shell)
32 super(ConfigMagics, self).__init__(shell)
33 self.configurables = []
33 self.configurables = []
34
34
35 @line_magic
35 @line_magic
36 def config(self, s):
36 def config(self, s):
37 """configure IPython
37 """configure IPython
38
38
39 %config Class[.trait=value]
39 %config Class[.trait=value]
40
40
41 This magic exposes most of the IPython config system. Any
41 This magic exposes most of the IPython config system. Any
42 Configurable class should be able to be configured with the simple
42 Configurable class should be able to be configured with the simple
43 line::
43 line::
44
44
45 %config Class.trait=value
45 %config Class.trait=value
46
46
47 Where `value` will be resolved in the user's namespace, if it is an
47 Where `value` will be resolved in the user's namespace, if it is an
48 expression or variable name.
48 expression or variable name.
49
49
50 Examples
50 Examples
51 --------
51 --------
52
52
53 To see what classes are available for config, pass no arguments::
53 To see what classes are available for config, pass no arguments::
54
54
55 In [1]: %config
55 In [1]: %config
56 Available objects for config:
56 Available objects for config:
57 TerminalInteractiveShell
57 TerminalInteractiveShell
58 HistoryManager
58 HistoryManager
59 PrefilterManager
59 PrefilterManager
60 AliasManager
60 AliasManager
61 IPCompleter
61 IPCompleter
62 DisplayFormatter
62 DisplayFormatter
63
63
64 To view what is configurable on a given class, just pass the class
64 To view what is configurable on a given class, just pass the class
65 name::
65 name::
66
66
67 In [2]: %config IPCompleter
67 In [2]: %config IPCompleter
68 IPCompleter options
68 IPCompleter options
69 -----------------
69 -----------------
70 IPCompleter.omit__names=<Enum>
70 IPCompleter.omit__names=<Enum>
71 Current: 2
71 Current: 2
72 Choices: (0, 1, 2)
72 Choices: (0, 1, 2)
73 Instruct the completer to omit private method names
73 Instruct the completer to omit private method names
74 Specifically, when completing on ``object.<tab>``.
74 Specifically, when completing on ``object.<tab>``.
75 When 2 [default]: all names that start with '_' will be excluded.
75 When 2 [default]: all names that start with '_' will be excluded.
76 When 1: all 'magic' names (``__foo__``) will be excluded.
76 When 1: all 'magic' names (``__foo__``) will be excluded.
77 When 0: nothing will be excluded.
77 When 0: nothing will be excluded.
78 IPCompleter.merge_completions=<CBool>
78 IPCompleter.merge_completions=<CBool>
79 Current: True
79 Current: True
80 Whether to merge completion results into a single list
80 Whether to merge completion results into a single list
81 If False, only the completion results from the first non-empty
81 If False, only the completion results from the first non-empty
82 completer will be returned.
82 completer will be returned.
83 IPCompleter.limit_to__all__=<CBool>
83 IPCompleter.limit_to__all__=<CBool>
84 Current: False
84 Current: False
85 Instruct the completer to use __all__ for the completion
85 Instruct the completer to use __all__ for the completion
86 Specifically, when completing on ``object.<tab>``.
86 Specifically, when completing on ``object.<tab>``.
87 When True: only those names in obj.__all__ will be included.
87 When True: only those names in obj.__all__ will be included.
88 When False [default]: the __all__ attribute is ignored
88 When False [default]: the __all__ attribute is ignored
89 IPCompleter.greedy=<CBool>
89 IPCompleter.greedy=<CBool>
90 Current: False
90 Current: False
91 Activate greedy completion
91 Activate greedy completion
92 This will enable completion on elements of lists, results of
92 This will enable completion on elements of lists, results of
93 function calls, etc., but can be unsafe because the code is
93 function calls, etc., but can be unsafe because the code is
94 actually evaluated on TAB.
94 actually evaluated on TAB.
95
95
96 but the real use is in setting values::
96 but the real use is in setting values::
97
97
98 In [3]: %config IPCompleter.greedy = True
98 In [3]: %config IPCompleter.greedy = True
99
99
100 and these values are read from the user_ns if they are variables::
100 and these values are read from the user_ns if they are variables::
101
101
102 In [4]: feeling_greedy=False
102 In [4]: feeling_greedy=False
103
103
104 In [5]: %config IPCompleter.greedy = feeling_greedy
104 In [5]: %config IPCompleter.greedy = feeling_greedy
105
105
106 """
106 """
107 from traitlets.config.loader import Config
107 from traitlets.config.loader import Config
108 # some IPython objects are Configurable, but do not yet have
108 # some IPython objects are Configurable, but do not yet have
109 # any configurable traits. Exclude them from the effects of
109 # any configurable traits. Exclude them from the effects of
110 # this magic, as their presence is just noise:
110 # this magic, as their presence is just noise:
111 configurables = sorted(set([ c for c in self.shell.configurables
111 configurables = sorted(set([ c for c in self.shell.configurables
112 if c.__class__.class_traits(config=True)
112 if c.__class__.class_traits(config=True)
113 ]), key=lambda x: x.__class__.__name__)
113 ]), key=lambda x: x.__class__.__name__)
114 classnames = [ c.__class__.__name__ for c in configurables ]
114 classnames = [ c.__class__.__name__ for c in configurables ]
115
115
116 line = s.strip()
116 line = s.strip()
117 if not line:
117 if not line:
118 # print available configurable names
118 # print available configurable names
119 print("Available objects for config:")
119 print("Available objects for config:")
120 for name in classnames:
120 for name in classnames:
121 print(" ", name)
121 print(" ", name)
122 return
122 return
123 elif line in classnames:
123 elif line in classnames:
124 # `%config TerminalInteractiveShell` will print trait info for
124 # `%config TerminalInteractiveShell` will print trait info for
125 # TerminalInteractiveShell
125 # TerminalInteractiveShell
126 c = configurables[classnames.index(line)]
126 c = configurables[classnames.index(line)]
127 cls = c.__class__
127 cls = c.__class__
128 help = cls.class_get_help(c)
128 help = cls.class_get_help(c)
129 # strip leading '--' from cl-args:
129 # strip leading '--' from cl-args:
130 help = re.sub(re.compile(r'^--', re.MULTILINE), '', help)
130 help = re.sub(re.compile(r'^--', re.MULTILINE), '', help)
131 print(help)
131 print(help)
132 return
132 return
133 elif reg.match(line):
133 elif reg.match(line):
134 cls, attr = line.split('.')
134 cls, attr = line.split('.')
135 return getattr(configurables[classnames.index(cls)],attr)
135 return getattr(configurables[classnames.index(cls)],attr)
136 elif '=' not in line:
136 elif '=' not in line:
137 msg = "Invalid config statement: %r, "\
137 msg = "Invalid config statement: %r, "\
138 "should be `Class.trait = value`."
138 "should be `Class.trait = value`."
139
139
140 ll = line.lower()
140 ll = line.lower()
141 for classname in classnames:
141 for classname in classnames:
142 if ll == classname.lower():
142 if ll == classname.lower():
143 msg = msg + '\nDid you mean %s (note the case)?' % classname
143 msg = msg + '\nDid you mean %s (note the case)?' % classname
144 break
144 break
145
145
146 raise UsageError( msg % line)
146 raise UsageError( msg % line)
147
147
148 # otherwise, assume we are setting configurables.
148 # otherwise, assume we are setting configurables.
149 # leave quotes on args when splitting, because we want
149 # leave quotes on args when splitting, because we want
150 # unquoted args to eval in user_ns
150 # unquoted args to eval in user_ns
151 cfg = Config()
151 cfg = Config()
152 exec("cfg."+line, locals(), self.shell.user_ns)
152 exec("cfg."+line, locals(), self.shell.user_ns)
153
153
154 for configurable in configurables:
154 for configurable in configurables:
155 try:
155 try:
156 configurable.update_config(cfg)
156 configurable.update_config(cfg)
157 except Exception as e:
157 except Exception as e:
158 error(e)
158 error(e)
@@ -1,1423 +1,1424 b''
1 # -*- coding: utf-8 -*-
1 # -*- coding: utf-8 -*-
2 """Implementation of execution-related magic functions."""
2 """Implementation of execution-related magic functions."""
3
3
4 # Copyright (c) IPython Development Team.
4 # Copyright (c) IPython Development Team.
5 # Distributed under the terms of the Modified BSD License.
5 # Distributed under the terms of the Modified BSD License.
6
6
7
7
8 import ast
8 import ast
9 import bdb
9 import bdb
10 import builtins as builtin_mod
10 import builtins as builtin_mod
11 import gc
11 import gc
12 import itertools
12 import itertools
13 import os
13 import os
14 import shlex
14 import shlex
15 import sys
15 import sys
16 import time
16 import time
17 import timeit
17 import timeit
18 import math
18 import math
19 from pdb import Restart
19 from pdb import Restart
20
20
21 # cProfile was added in Python2.5
21 # cProfile was added in Python2.5
22 try:
22 try:
23 import cProfile as profile
23 import cProfile as profile
24 import pstats
24 import pstats
25 except ImportError:
25 except ImportError:
26 # profile isn't bundled by default in Debian for license reasons
26 # profile isn't bundled by default in Debian for license reasons
27 try:
27 try:
28 import profile, pstats
28 import profile, pstats
29 except ImportError:
29 except ImportError:
30 profile = pstats = None
30 profile = pstats = None
31
31
32 from IPython.core import oinspect
32 from IPython.core import oinspect
33 from IPython.core import magic_arguments
33 from IPython.core import magic_arguments
34 from IPython.core import page
34 from IPython.core import page
35 from IPython.core.error import UsageError
35 from IPython.core.error import UsageError
36 from IPython.core.macro import Macro
36 from IPython.core.macro import Macro
37 from IPython.core.magic import (Magics, magics_class, line_magic, cell_magic,
37 from IPython.core.magic import (Magics, magics_class, line_magic, cell_magic,
38 line_cell_magic, on_off, needs_local_scope)
38 line_cell_magic, on_off, needs_local_scope)
39 from IPython.testing.skipdoctest import skip_doctest
39 from IPython.testing.skipdoctest import skip_doctest
40 from IPython.utils.contexts import preserve_keys
40 from IPython.utils.contexts import preserve_keys
41 from IPython.utils.capture import capture_output
41 from IPython.utils.capture import capture_output
42 from IPython.utils.ipstruct import Struct
42 from IPython.utils.ipstruct import Struct
43 from IPython.utils.module_paths import find_mod
43 from IPython.utils.module_paths import find_mod
44 from IPython.utils.path import get_py_filename, shellglob
44 from IPython.utils.path import get_py_filename, shellglob
45 from IPython.utils.timing import clock, clock2
45 from IPython.utils.timing import clock, clock2
46 from warnings import warn
46 from warnings import warn
47 from logging import error
47 from logging import error
48 from io import StringIO
48 from io import StringIO
49
49
50
50
51 #-----------------------------------------------------------------------------
51 #-----------------------------------------------------------------------------
52 # Magic implementation classes
52 # Magic implementation classes
53 #-----------------------------------------------------------------------------
53 #-----------------------------------------------------------------------------
54
54
55
55
56 class TimeitResult(object):
56 class TimeitResult(object):
57 """
57 """
58 Object returned by the timeit magic with info about the run.
58 Object returned by the timeit magic with info about the run.
59
59
60 Contains the following attributes :
60 Contains the following attributes :
61
61
62 loops: (int) number of loops done per measurement
62 loops: (int) number of loops done per measurement
63 repeat: (int) number of times the measurement has been repeated
63 repeat: (int) number of times the measurement has been repeated
64 best: (float) best execution time / number
64 best: (float) best execution time / number
65 all_runs: (list of float) execution time of each run (in s)
65 all_runs: (list of float) execution time of each run (in s)
66 compile_time: (float) time of statement compilation (s)
66 compile_time: (float) time of statement compilation (s)
67
67
68 """
68 """
69 def __init__(self, loops, repeat, best, worst, all_runs, compile_time, precision):
69 def __init__(self, loops, repeat, best, worst, all_runs, compile_time, precision):
70 self.loops = loops
70 self.loops = loops
71 self.repeat = repeat
71 self.repeat = repeat
72 self.best = best
72 self.best = best
73 self.worst = worst
73 self.worst = worst
74 self.all_runs = all_runs
74 self.all_runs = all_runs
75 self.compile_time = compile_time
75 self.compile_time = compile_time
76 self._precision = precision
76 self._precision = precision
77 self.timings = [ dt / self.loops for dt in all_runs]
77 self.timings = [ dt / self.loops for dt in all_runs]
78
78
79 @property
79 @property
80 def average(self):
80 def average(self):
81 return math.fsum(self.timings) / len(self.timings)
81 return math.fsum(self.timings) / len(self.timings)
82
82
83 @property
83 @property
84 def stdev(self):
84 def stdev(self):
85 mean = self.average
85 mean = self.average
86 return (math.fsum([(x - mean) ** 2 for x in self.timings]) / len(self.timings)) ** 0.5
86 return (math.fsum([(x - mean) ** 2 for x in self.timings]) / len(self.timings)) ** 0.5
87
87
88 def __str__(self):
88 def __str__(self):
89 pm = '+-'
89 pm = '+-'
90 if hasattr(sys.stdout, 'encoding') and sys.stdout.encoding:
90 if hasattr(sys.stdout, 'encoding') and sys.stdout.encoding:
91 try:
91 try:
92 u'\xb1'.encode(sys.stdout.encoding)
92 u'\xb1'.encode(sys.stdout.encoding)
93 pm = u'\xb1'
93 pm = u'\xb1'
94 except:
94 except:
95 pass
95 pass
96 return (
96 return (
97 u"{mean} {pm} {std} per loop (mean {pm} std. dev. of {runs} run{run_plural}, {loops} loop{loop_plural} each)"
97 u"{mean} {pm} {std} per loop (mean {pm} std. dev. of {runs} run{run_plural}, {loops} loop{loop_plural} each)"
98 .format(
98 .format(
99 pm = pm,
99 pm = pm,
100 runs = self.repeat,
100 runs = self.repeat,
101 loops = self.loops,
101 loops = self.loops,
102 loop_plural = "" if self.loops == 1 else "s",
102 loop_plural = "" if self.loops == 1 else "s",
103 run_plural = "" if self.repeat == 1 else "s",
103 run_plural = "" if self.repeat == 1 else "s",
104 mean = _format_time(self.average, self._precision),
104 mean = _format_time(self.average, self._precision),
105 std = _format_time(self.stdev, self._precision))
105 std = _format_time(self.stdev, self._precision))
106 )
106 )
107
107
108 def _repr_pretty_(self, p , cycle):
108 def _repr_pretty_(self, p , cycle):
109 unic = self.__str__()
109 unic = self.__str__()
110 p.text(u'<TimeitResult : '+unic+u'>')
110 p.text(u'<TimeitResult : '+unic+u'>')
111
111
112
112
113 class TimeitTemplateFiller(ast.NodeTransformer):
113 class TimeitTemplateFiller(ast.NodeTransformer):
114 """Fill in the AST template for timing execution.
114 """Fill in the AST template for timing execution.
115
115
116 This is quite closely tied to the template definition, which is in
116 This is quite closely tied to the template definition, which is in
117 :meth:`ExecutionMagics.timeit`.
117 :meth:`ExecutionMagics.timeit`.
118 """
118 """
119 def __init__(self, ast_setup, ast_stmt):
119 def __init__(self, ast_setup, ast_stmt):
120 self.ast_setup = ast_setup
120 self.ast_setup = ast_setup
121 self.ast_stmt = ast_stmt
121 self.ast_stmt = ast_stmt
122
122
123 def visit_FunctionDef(self, node):
123 def visit_FunctionDef(self, node):
124 "Fill in the setup statement"
124 "Fill in the setup statement"
125 self.generic_visit(node)
125 self.generic_visit(node)
126 if node.name == "inner":
126 if node.name == "inner":
127 node.body[:1] = self.ast_setup.body
127 node.body[:1] = self.ast_setup.body
128
128
129 return node
129 return node
130
130
131 def visit_For(self, node):
131 def visit_For(self, node):
132 "Fill in the statement to be timed"
132 "Fill in the statement to be timed"
133 if getattr(getattr(node.body[0], 'value', None), 'id', None) == 'stmt':
133 if getattr(getattr(node.body[0], 'value', None), 'id', None) == 'stmt':
134 node.body = self.ast_stmt.body
134 node.body = self.ast_stmt.body
135 return node
135 return node
136
136
137
137
138 class Timer(timeit.Timer):
138 class Timer(timeit.Timer):
139 """Timer class that explicitly uses self.inner
139 """Timer class that explicitly uses self.inner
140
140
141 which is an undocumented implementation detail of CPython,
141 which is an undocumented implementation detail of CPython,
142 not shared by PyPy.
142 not shared by PyPy.
143 """
143 """
144 # Timer.timeit copied from CPython 3.4.2
144 # Timer.timeit copied from CPython 3.4.2
145 def timeit(self, number=timeit.default_number):
145 def timeit(self, number=timeit.default_number):
146 """Time 'number' executions of the main statement.
146 """Time 'number' executions of the main statement.
147
147
148 To be precise, this executes the setup statement once, and
148 To be precise, this executes the setup statement once, and
149 then returns the time it takes to execute the main statement
149 then returns the time it takes to execute the main statement
150 a number of times, as a float measured in seconds. The
150 a number of times, as a float measured in seconds. The
151 argument is the number of times through the loop, defaulting
151 argument is the number of times through the loop, defaulting
152 to one million. The main statement, the setup statement and
152 to one million. The main statement, the setup statement and
153 the timer function to be used are passed to the constructor.
153 the timer function to be used are passed to the constructor.
154 """
154 """
155 it = itertools.repeat(None, number)
155 it = itertools.repeat(None, number)
156 gcold = gc.isenabled()
156 gcold = gc.isenabled()
157 gc.disable()
157 gc.disable()
158 try:
158 try:
159 timing = self.inner(it, self.timer)
159 timing = self.inner(it, self.timer)
160 finally:
160 finally:
161 if gcold:
161 if gcold:
162 gc.enable()
162 gc.enable()
163 return timing
163 return timing
164
164
165
165
166 @magics_class
166 @magics_class
167 class ExecutionMagics(Magics):
167 class ExecutionMagics(Magics):
168 """Magics related to code execution, debugging, profiling, etc.
168 """Magics related to code execution, debugging, profiling, etc.
169
169
170 """
170 """
171
171
172 def __init__(self, shell):
172 def __init__(self, shell):
173 super(ExecutionMagics, self).__init__(shell)
173 super(ExecutionMagics, self).__init__(shell)
174 if profile is None:
174 if profile is None:
175 self.prun = self.profile_missing_notice
175 self.prun = self.profile_missing_notice
176 # Default execution function used to actually run user code.
176 # Default execution function used to actually run user code.
177 self.default_runner = None
177 self.default_runner = None
178
178
179 def profile_missing_notice(self, *args, **kwargs):
179 def profile_missing_notice(self, *args, **kwargs):
180 error("""\
180 error("""\
181 The profile module could not be found. It has been removed from the standard
181 The profile module could not be found. It has been removed from the standard
182 python packages because of its non-free license. To use profiling, install the
182 python packages because of its non-free license. To use profiling, install the
183 python-profiler package from non-free.""")
183 python-profiler package from non-free.""")
184
184
185 @skip_doctest
185 @skip_doctest
186 @line_cell_magic
186 @line_cell_magic
187 def prun(self, parameter_s='', cell=None):
187 def prun(self, parameter_s='', cell=None):
188
188
189 """Run a statement through the python code profiler.
189 """Run a statement through the python code profiler.
190
190
191 Usage, in line mode:
191 Usage, in line mode:
192 %prun [options] statement
192 %prun [options] statement
193
193
194 Usage, in cell mode:
194 Usage, in cell mode:
195 %%prun [options] [statement]
195 %%prun [options] [statement]
196 code...
196 code...
197 code...
197 code...
198
198
199 In cell mode, the additional code lines are appended to the (possibly
199 In cell mode, the additional code lines are appended to the (possibly
200 empty) statement in the first line. Cell mode allows you to easily
200 empty) statement in the first line. Cell mode allows you to easily
201 profile multiline blocks without having to put them in a separate
201 profile multiline blocks without having to put them in a separate
202 function.
202 function.
203
203
204 The given statement (which doesn't require quote marks) is run via the
204 The given statement (which doesn't require quote marks) is run via the
205 python profiler in a manner similar to the profile.run() function.
205 python profiler in a manner similar to the profile.run() function.
206 Namespaces are internally managed to work correctly; profile.run
206 Namespaces are internally managed to work correctly; profile.run
207 cannot be used in IPython because it makes certain assumptions about
207 cannot be used in IPython because it makes certain assumptions about
208 namespaces which do not hold under IPython.
208 namespaces which do not hold under IPython.
209
209
210 Options:
210 Options:
211
211
212 -l <limit>
212 -l <limit>
213 you can place restrictions on what or how much of the
213 you can place restrictions on what or how much of the
214 profile gets printed. The limit value can be:
214 profile gets printed. The limit value can be:
215
215
216 * A string: only information for function names containing this string
216 * A string: only information for function names containing this string
217 is printed.
217 is printed.
218
218
219 * An integer: only these many lines are printed.
219 * An integer: only these many lines are printed.
220
220
221 * A float (between 0 and 1): this fraction of the report is printed
221 * A float (between 0 and 1): this fraction of the report is printed
222 (for example, use a limit of 0.4 to see the topmost 40% only).
222 (for example, use a limit of 0.4 to see the topmost 40% only).
223
223
224 You can combine several limits with repeated use of the option. For
224 You can combine several limits with repeated use of the option. For
225 example, ``-l __init__ -l 5`` will print only the topmost 5 lines of
225 example, ``-l __init__ -l 5`` will print only the topmost 5 lines of
226 information about class constructors.
226 information about class constructors.
227
227
228 -r
228 -r
229 return the pstats.Stats object generated by the profiling. This
229 return the pstats.Stats object generated by the profiling. This
230 object has all the information about the profile in it, and you can
230 object has all the information about the profile in it, and you can
231 later use it for further analysis or in other functions.
231 later use it for further analysis or in other functions.
232
232
233 -s <key>
233 -s <key>
234 sort profile by given key. You can provide more than one key
234 sort profile by given key. You can provide more than one key
235 by using the option several times: '-s key1 -s key2 -s key3...'. The
235 by using the option several times: '-s key1 -s key2 -s key3...'. The
236 default sorting key is 'time'.
236 default sorting key is 'time'.
237
237
238 The following is copied verbatim from the profile documentation
238 The following is copied verbatim from the profile documentation
239 referenced below:
239 referenced below:
240
240
241 When more than one key is provided, additional keys are used as
241 When more than one key is provided, additional keys are used as
242 secondary criteria when the there is equality in all keys selected
242 secondary criteria when the there is equality in all keys selected
243 before them.
243 before them.
244
244
245 Abbreviations can be used for any key names, as long as the
245 Abbreviations can be used for any key names, as long as the
246 abbreviation is unambiguous. The following are the keys currently
246 abbreviation is unambiguous. The following are the keys currently
247 defined:
247 defined:
248
248
249 ============ =====================
249 ============ =====================
250 Valid Arg Meaning
250 Valid Arg Meaning
251 ============ =====================
251 ============ =====================
252 "calls" call count
252 "calls" call count
253 "cumulative" cumulative time
253 "cumulative" cumulative time
254 "file" file name
254 "file" file name
255 "module" file name
255 "module" file name
256 "pcalls" primitive call count
256 "pcalls" primitive call count
257 "line" line number
257 "line" line number
258 "name" function name
258 "name" function name
259 "nfl" name/file/line
259 "nfl" name/file/line
260 "stdname" standard name
260 "stdname" standard name
261 "time" internal time
261 "time" internal time
262 ============ =====================
262 ============ =====================
263
263
264 Note that all sorts on statistics are in descending order (placing
264 Note that all sorts on statistics are in descending order (placing
265 most time consuming items first), where as name, file, and line number
265 most time consuming items first), where as name, file, and line number
266 searches are in ascending order (i.e., alphabetical). The subtle
266 searches are in ascending order (i.e., alphabetical). The subtle
267 distinction between "nfl" and "stdname" is that the standard name is a
267 distinction between "nfl" and "stdname" is that the standard name is a
268 sort of the name as printed, which means that the embedded line
268 sort of the name as printed, which means that the embedded line
269 numbers get compared in an odd way. For example, lines 3, 20, and 40
269 numbers get compared in an odd way. For example, lines 3, 20, and 40
270 would (if the file names were the same) appear in the string order
270 would (if the file names were the same) appear in the string order
271 "20" "3" and "40". In contrast, "nfl" does a numeric compare of the
271 "20" "3" and "40". In contrast, "nfl" does a numeric compare of the
272 line numbers. In fact, sort_stats("nfl") is the same as
272 line numbers. In fact, sort_stats("nfl") is the same as
273 sort_stats("name", "file", "line").
273 sort_stats("name", "file", "line").
274
274
275 -T <filename>
275 -T <filename>
276 save profile results as shown on screen to a text
276 save profile results as shown on screen to a text
277 file. The profile is still shown on screen.
277 file. The profile is still shown on screen.
278
278
279 -D <filename>
279 -D <filename>
280 save (via dump_stats) profile statistics to given
280 save (via dump_stats) profile statistics to given
281 filename. This data is in a format understood by the pstats module, and
281 filename. This data is in a format understood by the pstats module, and
282 is generated by a call to the dump_stats() method of profile
282 is generated by a call to the dump_stats() method of profile
283 objects. The profile is still shown on screen.
283 objects. The profile is still shown on screen.
284
284
285 -q
285 -q
286 suppress output to the pager. Best used with -T and/or -D above.
286 suppress output to the pager. Best used with -T and/or -D above.
287
287
288 If you want to run complete programs under the profiler's control, use
288 If you want to run complete programs under the profiler's control, use
289 ``%run -p [prof_opts] filename.py [args to program]`` where prof_opts
289 ``%run -p [prof_opts] filename.py [args to program]`` where prof_opts
290 contains profiler specific options as described here.
290 contains profiler specific options as described here.
291
291
292 You can read the complete documentation for the profile module with::
292 You can read the complete documentation for the profile module with::
293
293
294 In [1]: import profile; profile.help()
294 In [1]: import profile; profile.help()
295 """
295 """
296 opts, arg_str = self.parse_options(parameter_s, 'D:l:rs:T:q',
296 opts, arg_str = self.parse_options(parameter_s, 'D:l:rs:T:q',
297 list_all=True, posix=False)
297 list_all=True, posix=False)
298 if cell is not None:
298 if cell is not None:
299 arg_str += '\n' + cell
299 arg_str += '\n' + cell
300 arg_str = self.shell.transform_cell(arg_str)
300 arg_str = self.shell.transform_cell(arg_str)
301 return self._run_with_profiler(arg_str, opts, self.shell.user_ns)
301 return self._run_with_profiler(arg_str, opts, self.shell.user_ns)
302
302
303 def _run_with_profiler(self, code, opts, namespace):
303 def _run_with_profiler(self, code, opts, namespace):
304 """
304 """
305 Run `code` with profiler. Used by ``%prun`` and ``%run -p``.
305 Run `code` with profiler. Used by ``%prun`` and ``%run -p``.
306
306
307 Parameters
307 Parameters
308 ----------
308 ----------
309 code : str
309 code : str
310 Code to be executed.
310 Code to be executed.
311 opts : Struct
311 opts : Struct
312 Options parsed by `self.parse_options`.
312 Options parsed by `self.parse_options`.
313 namespace : dict
313 namespace : dict
314 A dictionary for Python namespace (e.g., `self.shell.user_ns`).
314 A dictionary for Python namespace (e.g., `self.shell.user_ns`).
315
315
316 """
316 """
317
317
318 # Fill default values for unspecified options:
318 # Fill default values for unspecified options:
319 opts.merge(Struct(D=[''], l=[], s=['time'], T=['']))
319 opts.merge(Struct(D=[''], l=[], s=['time'], T=['']))
320
320
321 prof = profile.Profile()
321 prof = profile.Profile()
322 try:
322 try:
323 prof = prof.runctx(code, namespace, namespace)
323 prof = prof.runctx(code, namespace, namespace)
324 sys_exit = ''
324 sys_exit = ''
325 except SystemExit:
325 except SystemExit:
326 sys_exit = """*** SystemExit exception caught in code being profiled."""
326 sys_exit = """*** SystemExit exception caught in code being profiled."""
327
327
328 stats = pstats.Stats(prof).strip_dirs().sort_stats(*opts.s)
328 stats = pstats.Stats(prof).strip_dirs().sort_stats(*opts.s)
329
329
330 lims = opts.l
330 lims = opts.l
331 if lims:
331 if lims:
332 lims = [] # rebuild lims with ints/floats/strings
332 lims = [] # rebuild lims with ints/floats/strings
333 for lim in opts.l:
333 for lim in opts.l:
334 try:
334 try:
335 lims.append(int(lim))
335 lims.append(int(lim))
336 except ValueError:
336 except ValueError:
337 try:
337 try:
338 lims.append(float(lim))
338 lims.append(float(lim))
339 except ValueError:
339 except ValueError:
340 lims.append(lim)
340 lims.append(lim)
341
341
342 # Trap output.
342 # Trap output.
343 stdout_trap = StringIO()
343 stdout_trap = StringIO()
344 stats_stream = stats.stream
344 stats_stream = stats.stream
345 try:
345 try:
346 stats.stream = stdout_trap
346 stats.stream = stdout_trap
347 stats.print_stats(*lims)
347 stats.print_stats(*lims)
348 finally:
348 finally:
349 stats.stream = stats_stream
349 stats.stream = stats_stream
350
350
351 output = stdout_trap.getvalue()
351 output = stdout_trap.getvalue()
352 output = output.rstrip()
352 output = output.rstrip()
353
353
354 if 'q' not in opts:
354 if 'q' not in opts:
355 page.page(output)
355 page.page(output)
356 print(sys_exit, end=' ')
356 print(sys_exit, end=' ')
357
357
358 dump_file = opts.D[0]
358 dump_file = opts.D[0]
359 text_file = opts.T[0]
359 text_file = opts.T[0]
360 if dump_file:
360 if dump_file:
361 prof.dump_stats(dump_file)
361 prof.dump_stats(dump_file)
362 print('\n*** Profile stats marshalled to file',\
362 print('\n*** Profile stats marshalled to file',\
363 repr(dump_file)+'.',sys_exit)
363 repr(dump_file)+'.',sys_exit)
364 if text_file:
364 if text_file:
365 pfile = open(text_file,'w')
365 pfile = open(text_file,'w')
366 pfile.write(output)
366 pfile.write(output)
367 pfile.close()
367 pfile.close()
368 print('\n*** Profile printout saved to text file',\
368 print('\n*** Profile printout saved to text file',\
369 repr(text_file)+'.',sys_exit)
369 repr(text_file)+'.',sys_exit)
370
370
371 if 'r' in opts:
371 if 'r' in opts:
372 return stats
372 return stats
373 else:
373 else:
374 return None
374 return None
375
375
376 @line_magic
376 @line_magic
377 def pdb(self, parameter_s=''):
377 def pdb(self, parameter_s=''):
378 """Control the automatic calling of the pdb interactive debugger.
378 """Control the automatic calling of the pdb interactive debugger.
379
379
380 Call as '%pdb on', '%pdb 1', '%pdb off' or '%pdb 0'. If called without
380 Call as '%pdb on', '%pdb 1', '%pdb off' or '%pdb 0'. If called without
381 argument it works as a toggle.
381 argument it works as a toggle.
382
382
383 When an exception is triggered, IPython can optionally call the
383 When an exception is triggered, IPython can optionally call the
384 interactive pdb debugger after the traceback printout. %pdb toggles
384 interactive pdb debugger after the traceback printout. %pdb toggles
385 this feature on and off.
385 this feature on and off.
386
386
387 The initial state of this feature is set in your configuration
387 The initial state of this feature is set in your configuration
388 file (the option is ``InteractiveShell.pdb``).
388 file (the option is ``InteractiveShell.pdb``).
389
389
390 If you want to just activate the debugger AFTER an exception has fired,
390 If you want to just activate the debugger AFTER an exception has fired,
391 without having to type '%pdb on' and rerunning your code, you can use
391 without having to type '%pdb on' and rerunning your code, you can use
392 the %debug magic."""
392 the %debug magic."""
393
393
394 par = parameter_s.strip().lower()
394 par = parameter_s.strip().lower()
395
395
396 if par:
396 if par:
397 try:
397 try:
398 new_pdb = {'off':0,'0':0,'on':1,'1':1}[par]
398 new_pdb = {'off':0,'0':0,'on':1,'1':1}[par]
399 except KeyError:
399 except KeyError:
400 print ('Incorrect argument. Use on/1, off/0, '
400 print ('Incorrect argument. Use on/1, off/0, '
401 'or nothing for a toggle.')
401 'or nothing for a toggle.')
402 return
402 return
403 else:
403 else:
404 # toggle
404 # toggle
405 new_pdb = not self.shell.call_pdb
405 new_pdb = not self.shell.call_pdb
406
406
407 # set on the shell
407 # set on the shell
408 self.shell.call_pdb = new_pdb
408 self.shell.call_pdb = new_pdb
409 print('Automatic pdb calling has been turned',on_off(new_pdb))
409 print('Automatic pdb calling has been turned',on_off(new_pdb))
410
410
411 @skip_doctest
411 @skip_doctest
412 @magic_arguments.magic_arguments()
412 @magic_arguments.magic_arguments()
413 @magic_arguments.argument('--breakpoint', '-b', metavar='FILE:LINE',
413 @magic_arguments.argument('--breakpoint', '-b', metavar='FILE:LINE',
414 help="""
414 help="""
415 Set break point at LINE in FILE.
415 Set break point at LINE in FILE.
416 """
416 """
417 )
417 )
418 @magic_arguments.argument('statement', nargs='*',
418 @magic_arguments.argument('statement', nargs='*',
419 help="""
419 help="""
420 Code to run in debugger.
420 Code to run in debugger.
421 You can omit this in cell magic mode.
421 You can omit this in cell magic mode.
422 """
422 """
423 )
423 )
424 @line_cell_magic
424 @line_cell_magic
425 def debug(self, line='', cell=None):
425 def debug(self, line='', cell=None):
426 """Activate the interactive debugger.
426 """Activate the interactive debugger.
427
427
428 This magic command support two ways of activating debugger.
428 This magic command support two ways of activating debugger.
429 One is to activate debugger before executing code. This way, you
429 One is to activate debugger before executing code. This way, you
430 can set a break point, to step through the code from the point.
430 can set a break point, to step through the code from the point.
431 You can use this mode by giving statements to execute and optionally
431 You can use this mode by giving statements to execute and optionally
432 a breakpoint.
432 a breakpoint.
433
433
434 The other one is to activate debugger in post-mortem mode. You can
434 The other one is to activate debugger in post-mortem mode. You can
435 activate this mode simply running %debug without any argument.
435 activate this mode simply running %debug without any argument.
436 If an exception has just occurred, this lets you inspect its stack
436 If an exception has just occurred, this lets you inspect its stack
437 frames interactively. Note that this will always work only on the last
437 frames interactively. Note that this will always work only on the last
438 traceback that occurred, so you must call this quickly after an
438 traceback that occurred, so you must call this quickly after an
439 exception that you wish to inspect has fired, because if another one
439 exception that you wish to inspect has fired, because if another one
440 occurs, it clobbers the previous one.
440 occurs, it clobbers the previous one.
441
441
442 If you want IPython to automatically do this on every exception, see
442 If you want IPython to automatically do this on every exception, see
443 the %pdb magic for more details.
443 the %pdb magic for more details.
444 """
444 """
445 args = magic_arguments.parse_argstring(self.debug, line)
445 args = magic_arguments.parse_argstring(self.debug, line)
446
446
447 if not (args.breakpoint or args.statement or cell):
447 if not (args.breakpoint or args.statement or cell):
448 self._debug_post_mortem()
448 self._debug_post_mortem()
449 else:
449 else:
450 code = "\n".join(args.statement)
450 code = "\n".join(args.statement)
451 if cell:
451 if cell:
452 code += "\n" + cell
452 code += "\n" + cell
453 self._debug_exec(code, args.breakpoint)
453 self._debug_exec(code, args.breakpoint)
454
454
455 def _debug_post_mortem(self):
455 def _debug_post_mortem(self):
456 self.shell.debugger(force=True)
456 self.shell.debugger(force=True)
457
457
458 def _debug_exec(self, code, breakpoint):
458 def _debug_exec(self, code, breakpoint):
459 if breakpoint:
459 if breakpoint:
460 (filename, bp_line) = breakpoint.rsplit(':', 1)
460 (filename, bp_line) = breakpoint.rsplit(':', 1)
461 bp_line = int(bp_line)
461 bp_line = int(bp_line)
462 else:
462 else:
463 (filename, bp_line) = (None, None)
463 (filename, bp_line) = (None, None)
464 self._run_with_debugger(code, self.shell.user_ns, filename, bp_line)
464 self._run_with_debugger(code, self.shell.user_ns, filename, bp_line)
465
465
466 @line_magic
466 @line_magic
467 def tb(self, s):
467 def tb(self, s):
468 """Print the last traceback with the currently active exception mode.
468 """Print the last traceback with the currently active exception mode.
469
469
470 See %xmode for changing exception reporting modes."""
470 See %xmode for changing exception reporting modes."""
471 self.shell.showtraceback()
471 self.shell.showtraceback()
472
472
473 @skip_doctest
473 @skip_doctest
474 @line_magic
474 @line_magic
475 def run(self, parameter_s='', runner=None,
475 def run(self, parameter_s='', runner=None,
476 file_finder=get_py_filename):
476 file_finder=get_py_filename):
477 """Run the named file inside IPython as a program.
477 """Run the named file inside IPython as a program.
478
478
479 Usage::
479 Usage::
480
480
481 %run [-n -i -e -G]
481 %run [-n -i -e -G]
482 [( -t [-N<N>] | -d [-b<N>] | -p [profile options] )]
482 [( -t [-N<N>] | -d [-b<N>] | -p [profile options] )]
483 ( -m mod | file ) [args]
483 ( -m mod | file ) [args]
484
484
485 Parameters after the filename are passed as command-line arguments to
485 Parameters after the filename are passed as command-line arguments to
486 the program (put in sys.argv). Then, control returns to IPython's
486 the program (put in sys.argv). Then, control returns to IPython's
487 prompt.
487 prompt.
488
488
489 This is similar to running at a system prompt ``python file args``,
489 This is similar to running at a system prompt ``python file args``,
490 but with the advantage of giving you IPython's tracebacks, and of
490 but with the advantage of giving you IPython's tracebacks, and of
491 loading all variables into your interactive namespace for further use
491 loading all variables into your interactive namespace for further use
492 (unless -p is used, see below).
492 (unless -p is used, see below).
493
493
494 The file is executed in a namespace initially consisting only of
494 The file is executed in a namespace initially consisting only of
495 ``__name__=='__main__'`` and sys.argv constructed as indicated. It thus
495 ``__name__=='__main__'`` and sys.argv constructed as indicated. It thus
496 sees its environment as if it were being run as a stand-alone program
496 sees its environment as if it were being run as a stand-alone program
497 (except for sharing global objects such as previously imported
497 (except for sharing global objects such as previously imported
498 modules). But after execution, the IPython interactive namespace gets
498 modules). But after execution, the IPython interactive namespace gets
499 updated with all variables defined in the program (except for __name__
499 updated with all variables defined in the program (except for __name__
500 and sys.argv). This allows for very convenient loading of code for
500 and sys.argv). This allows for very convenient loading of code for
501 interactive work, while giving each program a 'clean sheet' to run in.
501 interactive work, while giving each program a 'clean sheet' to run in.
502
502
503 Arguments are expanded using shell-like glob match. Patterns
503 Arguments are expanded using shell-like glob match. Patterns
504 '*', '?', '[seq]' and '[!seq]' can be used. Additionally,
504 '*', '?', '[seq]' and '[!seq]' can be used. Additionally,
505 tilde '~' will be expanded into user's home directory. Unlike
505 tilde '~' will be expanded into user's home directory. Unlike
506 real shells, quotation does not suppress expansions. Use
506 real shells, quotation does not suppress expansions. Use
507 *two* back slashes (e.g. ``\\\\*``) to suppress expansions.
507 *two* back slashes (e.g. ``\\\\*``) to suppress expansions.
508 To completely disable these expansions, you can use -G flag.
508 To completely disable these expansions, you can use -G flag.
509
509
510 Options:
510 Options:
511
511
512 -n
512 -n
513 __name__ is NOT set to '__main__', but to the running file's name
513 __name__ is NOT set to '__main__', but to the running file's name
514 without extension (as python does under import). This allows running
514 without extension (as python does under import). This allows running
515 scripts and reloading the definitions in them without calling code
515 scripts and reloading the definitions in them without calling code
516 protected by an ``if __name__ == "__main__"`` clause.
516 protected by an ``if __name__ == "__main__"`` clause.
517
517
518 -i
518 -i
519 run the file in IPython's namespace instead of an empty one. This
519 run the file in IPython's namespace instead of an empty one. This
520 is useful if you are experimenting with code written in a text editor
520 is useful if you are experimenting with code written in a text editor
521 which depends on variables defined interactively.
521 which depends on variables defined interactively.
522
522
523 -e
523 -e
524 ignore sys.exit() calls or SystemExit exceptions in the script
524 ignore sys.exit() calls or SystemExit exceptions in the script
525 being run. This is particularly useful if IPython is being used to
525 being run. This is particularly useful if IPython is being used to
526 run unittests, which always exit with a sys.exit() call. In such
526 run unittests, which always exit with a sys.exit() call. In such
527 cases you are interested in the output of the test results, not in
527 cases you are interested in the output of the test results, not in
528 seeing a traceback of the unittest module.
528 seeing a traceback of the unittest module.
529
529
530 -t
530 -t
531 print timing information at the end of the run. IPython will give
531 print timing information at the end of the run. IPython will give
532 you an estimated CPU time consumption for your script, which under
532 you an estimated CPU time consumption for your script, which under
533 Unix uses the resource module to avoid the wraparound problems of
533 Unix uses the resource module to avoid the wraparound problems of
534 time.clock(). Under Unix, an estimate of time spent on system tasks
534 time.clock(). Under Unix, an estimate of time spent on system tasks
535 is also given (for Windows platforms this is reported as 0.0).
535 is also given (for Windows platforms this is reported as 0.0).
536
536
537 If -t is given, an additional ``-N<N>`` option can be given, where <N>
537 If -t is given, an additional ``-N<N>`` option can be given, where <N>
538 must be an integer indicating how many times you want the script to
538 must be an integer indicating how many times you want the script to
539 run. The final timing report will include total and per run results.
539 run. The final timing report will include total and per run results.
540
540
541 For example (testing the script uniq_stable.py)::
541 For example (testing the script uniq_stable.py)::
542
542
543 In [1]: run -t uniq_stable
543 In [1]: run -t uniq_stable
544
544
545 IPython CPU timings (estimated):
545 IPython CPU timings (estimated):
546 User : 0.19597 s.
546 User : 0.19597 s.
547 System: 0.0 s.
547 System: 0.0 s.
548
548
549 In [2]: run -t -N5 uniq_stable
549 In [2]: run -t -N5 uniq_stable
550
550
551 IPython CPU timings (estimated):
551 IPython CPU timings (estimated):
552 Total runs performed: 5
552 Total runs performed: 5
553 Times : Total Per run
553 Times : Total Per run
554 User : 0.910862 s, 0.1821724 s.
554 User : 0.910862 s, 0.1821724 s.
555 System: 0.0 s, 0.0 s.
555 System: 0.0 s, 0.0 s.
556
556
557 -d
557 -d
558 run your program under the control of pdb, the Python debugger.
558 run your program under the control of pdb, the Python debugger.
559 This allows you to execute your program step by step, watch variables,
559 This allows you to execute your program step by step, watch variables,
560 etc. Internally, what IPython does is similar to calling::
560 etc. Internally, what IPython does is similar to calling::
561
561
562 pdb.run('execfile("YOURFILENAME")')
562 pdb.run('execfile("YOURFILENAME")')
563
563
564 with a breakpoint set on line 1 of your file. You can change the line
564 with a breakpoint set on line 1 of your file. You can change the line
565 number for this automatic breakpoint to be <N> by using the -bN option
565 number for this automatic breakpoint to be <N> by using the -bN option
566 (where N must be an integer). For example::
566 (where N must be an integer). For example::
567
567
568 %run -d -b40 myscript
568 %run -d -b40 myscript
569
569
570 will set the first breakpoint at line 40 in myscript.py. Note that
570 will set the first breakpoint at line 40 in myscript.py. Note that
571 the first breakpoint must be set on a line which actually does
571 the first breakpoint must be set on a line which actually does
572 something (not a comment or docstring) for it to stop execution.
572 something (not a comment or docstring) for it to stop execution.
573
573
574 Or you can specify a breakpoint in a different file::
574 Or you can specify a breakpoint in a different file::
575
575
576 %run -d -b myotherfile.py:20 myscript
576 %run -d -b myotherfile.py:20 myscript
577
577
578 When the pdb debugger starts, you will see a (Pdb) prompt. You must
578 When the pdb debugger starts, you will see a (Pdb) prompt. You must
579 first enter 'c' (without quotes) to start execution up to the first
579 first enter 'c' (without quotes) to start execution up to the first
580 breakpoint.
580 breakpoint.
581
581
582 Entering 'help' gives information about the use of the debugger. You
582 Entering 'help' gives information about the use of the debugger. You
583 can easily see pdb's full documentation with "import pdb;pdb.help()"
583 can easily see pdb's full documentation with "import pdb;pdb.help()"
584 at a prompt.
584 at a prompt.
585
585
586 -p
586 -p
587 run program under the control of the Python profiler module (which
587 run program under the control of the Python profiler module (which
588 prints a detailed report of execution times, function calls, etc).
588 prints a detailed report of execution times, function calls, etc).
589
589
590 You can pass other options after -p which affect the behavior of the
590 You can pass other options after -p which affect the behavior of the
591 profiler itself. See the docs for %prun for details.
591 profiler itself. See the docs for %prun for details.
592
592
593 In this mode, the program's variables do NOT propagate back to the
593 In this mode, the program's variables do NOT propagate back to the
594 IPython interactive namespace (because they remain in the namespace
594 IPython interactive namespace (because they remain in the namespace
595 where the profiler executes them).
595 where the profiler executes them).
596
596
597 Internally this triggers a call to %prun, see its documentation for
597 Internally this triggers a call to %prun, see its documentation for
598 details on the options available specifically for profiling.
598 details on the options available specifically for profiling.
599
599
600 There is one special usage for which the text above doesn't apply:
600 There is one special usage for which the text above doesn't apply:
601 if the filename ends with .ipy[nb], the file is run as ipython script,
601 if the filename ends with .ipy[nb], the file is run as ipython script,
602 just as if the commands were written on IPython prompt.
602 just as if the commands were written on IPython prompt.
603
603
604 -m
604 -m
605 specify module name to load instead of script path. Similar to
605 specify module name to load instead of script path. Similar to
606 the -m option for the python interpreter. Use this option last if you
606 the -m option for the python interpreter. Use this option last if you
607 want to combine with other %run options. Unlike the python interpreter
607 want to combine with other %run options. Unlike the python interpreter
608 only source modules are allowed no .pyc or .pyo files.
608 only source modules are allowed no .pyc or .pyo files.
609 For example::
609 For example::
610
610
611 %run -m example
611 %run -m example
612
612
613 will run the example module.
613 will run the example module.
614
614
615 -G
615 -G
616 disable shell-like glob expansion of arguments.
616 disable shell-like glob expansion of arguments.
617
617
618 """
618 """
619
619
620 # Logic to handle issue #3664
620 # Logic to handle issue #3664
621 # Add '--' after '-m <module_name>' to ignore additional args passed to a module.
621 # Add '--' after '-m <module_name>' to ignore additional args passed to a module.
622 if '-m' in parameter_s and '--' not in parameter_s:
622 if '-m' in parameter_s and '--' not in parameter_s:
623 argv = shlex.split(parameter_s, posix=(os.name == 'posix'))
623 argv = shlex.split(parameter_s, posix=(os.name == 'posix'))
624 for idx, arg in enumerate(argv):
624 for idx, arg in enumerate(argv):
625 if arg and arg.startswith('-') and arg != '-':
625 if arg and arg.startswith('-') and arg != '-':
626 if arg == '-m':
626 if arg == '-m':
627 argv.insert(idx + 2, '--')
627 argv.insert(idx + 2, '--')
628 break
628 break
629 else:
629 else:
630 # Positional arg, break
630 # Positional arg, break
631 break
631 break
632 parameter_s = ' '.join(shlex.quote(arg) for arg in argv)
632 parameter_s = ' '.join(shlex.quote(arg) for arg in argv)
633
633
634 # get arguments and set sys.argv for program to be run.
634 # get arguments and set sys.argv for program to be run.
635 opts, arg_lst = self.parse_options(parameter_s,
635 opts, arg_lst = self.parse_options(parameter_s,
636 'nidtN:b:pD:l:rs:T:em:G',
636 'nidtN:b:pD:l:rs:T:em:G',
637 mode='list', list_all=1)
637 mode='list', list_all=1)
638 if "m" in opts:
638 if "m" in opts:
639 modulename = opts["m"][0]
639 modulename = opts["m"][0]
640 modpath = find_mod(modulename)
640 modpath = find_mod(modulename)
641 if modpath is None:
641 if modpath is None:
642 warn('%r is not a valid modulename on sys.path'%modulename)
642 warn('%r is not a valid modulename on sys.path'%modulename)
643 return
643 return
644 arg_lst = [modpath] + arg_lst
644 arg_lst = [modpath] + arg_lst
645 try:
645 try:
646 filename = file_finder(arg_lst[0])
646 filename = file_finder(arg_lst[0])
647 except IndexError:
647 except IndexError:
648 warn('you must provide at least a filename.')
648 warn('you must provide at least a filename.')
649 print('\n%run:\n', oinspect.getdoc(self.run))
649 print('\n%run:\n', oinspect.getdoc(self.run))
650 return
650 return
651 except IOError as e:
651 except IOError as e:
652 try:
652 try:
653 msg = str(e)
653 msg = str(e)
654 except UnicodeError:
654 except UnicodeError:
655 msg = e.message
655 msg = e.message
656 error(msg)
656 error(msg)
657 return
657 return
658
658
659 if filename.lower().endswith(('.ipy', '.ipynb')):
659 if filename.lower().endswith(('.ipy', '.ipynb')):
660 with preserve_keys(self.shell.user_ns, '__file__'):
660 with preserve_keys(self.shell.user_ns, '__file__'):
661 self.shell.user_ns['__file__'] = filename
661 self.shell.user_ns['__file__'] = filename
662 self.shell.safe_execfile_ipy(filename)
662 self.shell.safe_execfile_ipy(filename)
663 return
663 return
664
664
665 # Control the response to exit() calls made by the script being run
665 # Control the response to exit() calls made by the script being run
666 exit_ignore = 'e' in opts
666 exit_ignore = 'e' in opts
667
667
668 # Make sure that the running script gets a proper sys.argv as if it
668 # Make sure that the running script gets a proper sys.argv as if it
669 # were run from a system shell.
669 # were run from a system shell.
670 save_argv = sys.argv # save it for later restoring
670 save_argv = sys.argv # save it for later restoring
671
671
672 if 'G' in opts:
672 if 'G' in opts:
673 args = arg_lst[1:]
673 args = arg_lst[1:]
674 else:
674 else:
675 # tilde and glob expansion
675 # tilde and glob expansion
676 args = shellglob(map(os.path.expanduser, arg_lst[1:]))
676 args = shellglob(map(os.path.expanduser, arg_lst[1:]))
677
677
678 sys.argv = [filename] + args # put in the proper filename
678 sys.argv = [filename] + args # put in the proper filename
679
679
680 if 'n' in opts:
680 if 'n' in opts:
681 name = os.path.splitext(os.path.basename(filename))[0]
681 name = os.path.splitext(os.path.basename(filename))[0]
682 else:
682 else:
683 name = '__main__'
683 name = '__main__'
684
684
685 if 'i' in opts:
685 if 'i' in opts:
686 # Run in user's interactive namespace
686 # Run in user's interactive namespace
687 prog_ns = self.shell.user_ns
687 prog_ns = self.shell.user_ns
688 __name__save = self.shell.user_ns['__name__']
688 __name__save = self.shell.user_ns['__name__']
689 prog_ns['__name__'] = name
689 prog_ns['__name__'] = name
690 main_mod = self.shell.user_module
690 main_mod = self.shell.user_module
691
691
692 # Since '%run foo' emulates 'python foo.py' at the cmd line, we must
692 # Since '%run foo' emulates 'python foo.py' at the cmd line, we must
693 # set the __file__ global in the script's namespace
693 # set the __file__ global in the script's namespace
694 # TK: Is this necessary in interactive mode?
694 # TK: Is this necessary in interactive mode?
695 prog_ns['__file__'] = filename
695 prog_ns['__file__'] = filename
696 else:
696 else:
697 # Run in a fresh, empty namespace
697 # Run in a fresh, empty namespace
698
698
699 # The shell MUST hold a reference to prog_ns so after %run
699 # The shell MUST hold a reference to prog_ns so after %run
700 # exits, the python deletion mechanism doesn't zero it out
700 # exits, the python deletion mechanism doesn't zero it out
701 # (leaving dangling references). See interactiveshell for details
701 # (leaving dangling references). See interactiveshell for details
702 main_mod = self.shell.new_main_mod(filename, name)
702 main_mod = self.shell.new_main_mod(filename, name)
703 prog_ns = main_mod.__dict__
703 prog_ns = main_mod.__dict__
704
704
705 # pickle fix. See interactiveshell for an explanation. But we need to
705 # pickle fix. See interactiveshell for an explanation. But we need to
706 # make sure that, if we overwrite __main__, we replace it at the end
706 # make sure that, if we overwrite __main__, we replace it at the end
707 main_mod_name = prog_ns['__name__']
707 main_mod_name = prog_ns['__name__']
708
708
709 if main_mod_name == '__main__':
709 if main_mod_name == '__main__':
710 restore_main = sys.modules['__main__']
710 restore_main = sys.modules['__main__']
711 else:
711 else:
712 restore_main = False
712 restore_main = False
713
713
714 # This needs to be undone at the end to prevent holding references to
714 # This needs to be undone at the end to prevent holding references to
715 # every single object ever created.
715 # every single object ever created.
716 sys.modules[main_mod_name] = main_mod
716 sys.modules[main_mod_name] = main_mod
717
717
718 if 'p' in opts or 'd' in opts:
718 if 'p' in opts or 'd' in opts:
719 if 'm' in opts:
719 if 'm' in opts:
720 code = 'run_module(modulename, prog_ns)'
720 code = 'run_module(modulename, prog_ns)'
721 code_ns = {
721 code_ns = {
722 'run_module': self.shell.safe_run_module,
722 'run_module': self.shell.safe_run_module,
723 'prog_ns': prog_ns,
723 'prog_ns': prog_ns,
724 'modulename': modulename,
724 'modulename': modulename,
725 }
725 }
726 else:
726 else:
727 if 'd' in opts:
727 if 'd' in opts:
728 # allow exceptions to raise in debug mode
728 # allow exceptions to raise in debug mode
729 code = 'execfile(filename, prog_ns, raise_exceptions=True)'
729 code = 'execfile(filename, prog_ns, raise_exceptions=True)'
730 else:
730 else:
731 code = 'execfile(filename, prog_ns)'
731 code = 'execfile(filename, prog_ns)'
732 code_ns = {
732 code_ns = {
733 'execfile': self.shell.safe_execfile,
733 'execfile': self.shell.safe_execfile,
734 'prog_ns': prog_ns,
734 'prog_ns': prog_ns,
735 'filename': get_py_filename(filename),
735 'filename': get_py_filename(filename),
736 }
736 }
737
737
738 try:
738 try:
739 stats = None
739 stats = None
740 if 'p' in opts:
740 if 'p' in opts:
741 stats = self._run_with_profiler(code, opts, code_ns)
741 stats = self._run_with_profiler(code, opts, code_ns)
742 else:
742 else:
743 if 'd' in opts:
743 if 'd' in opts:
744 bp_file, bp_line = parse_breakpoint(
744 bp_file, bp_line = parse_breakpoint(
745 opts.get('b', ['1'])[0], filename)
745 opts.get('b', ['1'])[0], filename)
746 self._run_with_debugger(
746 self._run_with_debugger(
747 code, code_ns, filename, bp_line, bp_file)
747 code, code_ns, filename, bp_line, bp_file)
748 else:
748 else:
749 if 'm' in opts:
749 if 'm' in opts:
750 def run():
750 def run():
751 self.shell.safe_run_module(modulename, prog_ns)
751 self.shell.safe_run_module(modulename, prog_ns)
752 else:
752 else:
753 if runner is None:
753 if runner is None:
754 runner = self.default_runner
754 runner = self.default_runner
755 if runner is None:
755 if runner is None:
756 runner = self.shell.safe_execfile
756 runner = self.shell.safe_execfile
757
757
758 def run():
758 def run():
759 runner(filename, prog_ns, prog_ns,
759 runner(filename, prog_ns, prog_ns,
760 exit_ignore=exit_ignore)
760 exit_ignore=exit_ignore)
761
761
762 if 't' in opts:
762 if 't' in opts:
763 # timed execution
763 # timed execution
764 try:
764 try:
765 nruns = int(opts['N'][0])
765 nruns = int(opts['N'][0])
766 if nruns < 1:
766 if nruns < 1:
767 error('Number of runs must be >=1')
767 error('Number of runs must be >=1')
768 return
768 return
769 except (KeyError):
769 except (KeyError):
770 nruns = 1
770 nruns = 1
771 self._run_with_timing(run, nruns)
771 self._run_with_timing(run, nruns)
772 else:
772 else:
773 # regular execution
773 # regular execution
774 run()
774 run()
775
775
776 if 'i' in opts:
776 if 'i' in opts:
777 self.shell.user_ns['__name__'] = __name__save
777 self.shell.user_ns['__name__'] = __name__save
778 else:
778 else:
779 # update IPython interactive namespace
779 # update IPython interactive namespace
780
780
781 # Some forms of read errors on the file may mean the
781 # Some forms of read errors on the file may mean the
782 # __name__ key was never set; using pop we don't have to
782 # __name__ key was never set; using pop we don't have to
783 # worry about a possible KeyError.
783 # worry about a possible KeyError.
784 prog_ns.pop('__name__', None)
784 prog_ns.pop('__name__', None)
785
785
786 with preserve_keys(self.shell.user_ns, '__file__'):
786 with preserve_keys(self.shell.user_ns, '__file__'):
787 self.shell.user_ns.update(prog_ns)
787 self.shell.user_ns.update(prog_ns)
788 finally:
788 finally:
789 # It's a bit of a mystery why, but __builtins__ can change from
789 # It's a bit of a mystery why, but __builtins__ can change from
790 # being a module to becoming a dict missing some key data after
790 # being a module to becoming a dict missing some key data after
791 # %run. As best I can see, this is NOT something IPython is doing
791 # %run. As best I can see, this is NOT something IPython is doing
792 # at all, and similar problems have been reported before:
792 # at all, and similar problems have been reported before:
793 # http://coding.derkeiler.com/Archive/Python/comp.lang.python/2004-10/0188.html
793 # http://coding.derkeiler.com/Archive/Python/comp.lang.python/2004-10/0188.html
794 # Since this seems to be done by the interpreter itself, the best
794 # Since this seems to be done by the interpreter itself, the best
795 # we can do is to at least restore __builtins__ for the user on
795 # we can do is to at least restore __builtins__ for the user on
796 # exit.
796 # exit.
797 self.shell.user_ns['__builtins__'] = builtin_mod
797 self.shell.user_ns['__builtins__'] = builtin_mod
798
798
799 # Ensure key global structures are restored
799 # Ensure key global structures are restored
800 sys.argv = save_argv
800 sys.argv = save_argv
801 if restore_main:
801 if restore_main:
802 sys.modules['__main__'] = restore_main
802 sys.modules['__main__'] = restore_main
803 else:
803 else:
804 # Remove from sys.modules the reference to main_mod we'd
804 # Remove from sys.modules the reference to main_mod we'd
805 # added. Otherwise it will trap references to objects
805 # added. Otherwise it will trap references to objects
806 # contained therein.
806 # contained therein.
807 del sys.modules[main_mod_name]
807 del sys.modules[main_mod_name]
808
808
809 return stats
809 return stats
810
810
811 def _run_with_debugger(self, code, code_ns, filename=None,
811 def _run_with_debugger(self, code, code_ns, filename=None,
812 bp_line=None, bp_file=None):
812 bp_line=None, bp_file=None):
813 """
813 """
814 Run `code` in debugger with a break point.
814 Run `code` in debugger with a break point.
815
815
816 Parameters
816 Parameters
817 ----------
817 ----------
818 code : str
818 code : str
819 Code to execute.
819 Code to execute.
820 code_ns : dict
820 code_ns : dict
821 A namespace in which `code` is executed.
821 A namespace in which `code` is executed.
822 filename : str
822 filename : str
823 `code` is ran as if it is in `filename`.
823 `code` is ran as if it is in `filename`.
824 bp_line : int, optional
824 bp_line : int, optional
825 Line number of the break point.
825 Line number of the break point.
826 bp_file : str, optional
826 bp_file : str, optional
827 Path to the file in which break point is specified.
827 Path to the file in which break point is specified.
828 `filename` is used if not given.
828 `filename` is used if not given.
829
829
830 Raises
830 Raises
831 ------
831 ------
832 UsageError
832 UsageError
833 If the break point given by `bp_line` is not valid.
833 If the break point given by `bp_line` is not valid.
834
834
835 """
835 """
836 deb = self.shell.InteractiveTB.pdb
836 deb = self.shell.InteractiveTB.pdb
837 if not deb:
837 if not deb:
838 self.shell.InteractiveTB.pdb = self.shell.InteractiveTB.debugger_cls()
838 self.shell.InteractiveTB.pdb = self.shell.InteractiveTB.debugger_cls()
839 deb = self.shell.InteractiveTB.pdb
839 deb = self.shell.InteractiveTB.pdb
840
840
841 # deb.checkline() fails if deb.curframe exists but is None; it can
841 # deb.checkline() fails if deb.curframe exists but is None; it can
842 # handle it not existing. https://github.com/ipython/ipython/issues/10028
842 # handle it not existing. https://github.com/ipython/ipython/issues/10028
843 if hasattr(deb, 'curframe'):
843 if hasattr(deb, 'curframe'):
844 del deb.curframe
844 del deb.curframe
845
845
846 # reset Breakpoint state, which is moronically kept
846 # reset Breakpoint state, which is moronically kept
847 # in a class
847 # in a class
848 bdb.Breakpoint.next = 1
848 bdb.Breakpoint.next = 1
849 bdb.Breakpoint.bplist = {}
849 bdb.Breakpoint.bplist = {}
850 bdb.Breakpoint.bpbynumber = [None]
850 bdb.Breakpoint.bpbynumber = [None]
851 deb.clear_all_breaks()
851 deb.clear_all_breaks()
852 if bp_line is not None:
852 if bp_line is not None:
853 # Set an initial breakpoint to stop execution
853 # Set an initial breakpoint to stop execution
854 maxtries = 10
854 maxtries = 10
855 bp_file = bp_file or filename
855 bp_file = bp_file or filename
856 checkline = deb.checkline(bp_file, bp_line)
856 checkline = deb.checkline(bp_file, bp_line)
857 if not checkline:
857 if not checkline:
858 for bp in range(bp_line + 1, bp_line + maxtries + 1):
858 for bp in range(bp_line + 1, bp_line + maxtries + 1):
859 if deb.checkline(bp_file, bp):
859 if deb.checkline(bp_file, bp):
860 break
860 break
861 else:
861 else:
862 msg = ("\nI failed to find a valid line to set "
862 msg = ("\nI failed to find a valid line to set "
863 "a breakpoint\n"
863 "a breakpoint\n"
864 "after trying up to line: %s.\n"
864 "after trying up to line: %s.\n"
865 "Please set a valid breakpoint manually "
865 "Please set a valid breakpoint manually "
866 "with the -b option." % bp)
866 "with the -b option." % bp)
867 raise UsageError(msg)
867 raise UsageError(msg)
868 # if we find a good linenumber, set the breakpoint
868 # if we find a good linenumber, set the breakpoint
869 deb.do_break('%s:%s' % (bp_file, bp_line))
869 deb.do_break('%s:%s' % (bp_file, bp_line))
870
870
871 if filename:
871 if filename:
872 # Mimic Pdb._runscript(...)
872 # Mimic Pdb._runscript(...)
873 deb._wait_for_mainpyfile = True
873 deb._wait_for_mainpyfile = True
874 deb.mainpyfile = deb.canonic(filename)
874 deb.mainpyfile = deb.canonic(filename)
875
875
876 # Start file run
876 # Start file run
877 print("NOTE: Enter 'c' at the %s prompt to continue execution." % deb.prompt)
877 print("NOTE: Enter 'c' at the %s prompt to continue execution." % deb.prompt)
878 try:
878 try:
879 if filename:
879 if filename:
880 # save filename so it can be used by methods on the deb object
880 # save filename so it can be used by methods on the deb object
881 deb._exec_filename = filename
881 deb._exec_filename = filename
882 while True:
882 while True:
883 try:
883 try:
884 deb.run(code, code_ns)
884 deb.run(code, code_ns)
885 except Restart:
885 except Restart:
886 print("Restarting")
886 print("Restarting")
887 if filename:
887 if filename:
888 deb._wait_for_mainpyfile = True
888 deb._wait_for_mainpyfile = True
889 deb.mainpyfile = deb.canonic(filename)
889 deb.mainpyfile = deb.canonic(filename)
890 continue
890 continue
891 else:
891 else:
892 break
892 break
893
893
894
894
895 except:
895 except:
896 etype, value, tb = sys.exc_info()
896 etype, value, tb = sys.exc_info()
897 # Skip three frames in the traceback: the %run one,
897 # Skip three frames in the traceback: the %run one,
898 # one inside bdb.py, and the command-line typed by the
898 # one inside bdb.py, and the command-line typed by the
899 # user (run by exec in pdb itself).
899 # user (run by exec in pdb itself).
900 self.shell.InteractiveTB(etype, value, tb, tb_offset=3)
900 self.shell.InteractiveTB(etype, value, tb, tb_offset=3)
901
901
902 @staticmethod
902 @staticmethod
903 def _run_with_timing(run, nruns):
903 def _run_with_timing(run, nruns):
904 """
904 """
905 Run function `run` and print timing information.
905 Run function `run` and print timing information.
906
906
907 Parameters
907 Parameters
908 ----------
908 ----------
909 run : callable
909 run : callable
910 Any callable object which takes no argument.
910 Any callable object which takes no argument.
911 nruns : int
911 nruns : int
912 Number of times to execute `run`.
912 Number of times to execute `run`.
913
913
914 """
914 """
915 twall0 = time.time()
915 twall0 = time.time()
916 if nruns == 1:
916 if nruns == 1:
917 t0 = clock2()
917 t0 = clock2()
918 run()
918 run()
919 t1 = clock2()
919 t1 = clock2()
920 t_usr = t1[0] - t0[0]
920 t_usr = t1[0] - t0[0]
921 t_sys = t1[1] - t0[1]
921 t_sys = t1[1] - t0[1]
922 print("\nIPython CPU timings (estimated):")
922 print("\nIPython CPU timings (estimated):")
923 print(" User : %10.2f s." % t_usr)
923 print(" User : %10.2f s." % t_usr)
924 print(" System : %10.2f s." % t_sys)
924 print(" System : %10.2f s." % t_sys)
925 else:
925 else:
926 runs = range(nruns)
926 runs = range(nruns)
927 t0 = clock2()
927 t0 = clock2()
928 for nr in runs:
928 for nr in runs:
929 run()
929 run()
930 t1 = clock2()
930 t1 = clock2()
931 t_usr = t1[0] - t0[0]
931 t_usr = t1[0] - t0[0]
932 t_sys = t1[1] - t0[1]
932 t_sys = t1[1] - t0[1]
933 print("\nIPython CPU timings (estimated):")
933 print("\nIPython CPU timings (estimated):")
934 print("Total runs performed:", nruns)
934 print("Total runs performed:", nruns)
935 print(" Times : %10s %10s" % ('Total', 'Per run'))
935 print(" Times : %10s %10s" % ('Total', 'Per run'))
936 print(" User : %10.2f s, %10.2f s." % (t_usr, t_usr / nruns))
936 print(" User : %10.2f s, %10.2f s." % (t_usr, t_usr / nruns))
937 print(" System : %10.2f s, %10.2f s." % (t_sys, t_sys / nruns))
937 print(" System : %10.2f s, %10.2f s." % (t_sys, t_sys / nruns))
938 twall1 = time.time()
938 twall1 = time.time()
939 print("Wall time: %10.2f s." % (twall1 - twall0))
939 print("Wall time: %10.2f s." % (twall1 - twall0))
940
940
941 @skip_doctest
941 @skip_doctest
942 @line_cell_magic
942 @line_cell_magic
943 @needs_local_scope
943 @needs_local_scope
944 def timeit(self, line='', cell=None, local_ns=None):
944 def timeit(self, line='', cell=None, local_ns=None):
945 """Time execution of a Python statement or expression
945 """Time execution of a Python statement or expression
946
946
947 Usage, in line mode:
947 Usage, in line mode:
948 %timeit [-n<N> -r<R> [-t|-c] -q -p<P> -o] statement
948 %timeit [-n<N> -r<R> [-t|-c] -q -p<P> -o] statement
949 or in cell mode:
949 or in cell mode:
950 %%timeit [-n<N> -r<R> [-t|-c] -q -p<P> -o] setup_code
950 %%timeit [-n<N> -r<R> [-t|-c] -q -p<P> -o] setup_code
951 code
951 code
952 code...
952 code...
953
953
954 Time execution of a Python statement or expression using the timeit
954 Time execution of a Python statement or expression using the timeit
955 module. This function can be used both as a line and cell magic:
955 module. This function can be used both as a line and cell magic:
956
956
957 - In line mode you can time a single-line statement (though multiple
957 - In line mode you can time a single-line statement (though multiple
958 ones can be chained with using semicolons).
958 ones can be chained with using semicolons).
959
959
960 - In cell mode, the statement in the first line is used as setup code
960 - In cell mode, the statement in the first line is used as setup code
961 (executed but not timed) and the body of the cell is timed. The cell
961 (executed but not timed) and the body of the cell is timed. The cell
962 body has access to any variables created in the setup code.
962 body has access to any variables created in the setup code.
963
963
964 Options:
964 Options:
965 -n<N>: execute the given statement <N> times in a loop. If this value
965 -n<N>: execute the given statement <N> times in a loop. If <N> is not
966 is not given, a fitting value is chosen.
966 provided, <N> is determined so as to get sufficient accuracy.
967
967
968 -r<R>: repeat the loop iteration <R> times and take the best result.
968 -r<R>: number of repeats <R>, each consisting of <N> loops, and take the
969 Default: 3
969 best result.
970 Default: 7
970
971
971 -t: use time.time to measure the time, which is the default on Unix.
972 -t: use time.time to measure the time, which is the default on Unix.
972 This function measures wall time.
973 This function measures wall time.
973
974
974 -c: use time.clock to measure the time, which is the default on
975 -c: use time.clock to measure the time, which is the default on
975 Windows and measures wall time. On Unix, resource.getrusage is used
976 Windows and measures wall time. On Unix, resource.getrusage is used
976 instead and returns the CPU user time.
977 instead and returns the CPU user time.
977
978
978 -p<P>: use a precision of <P> digits to display the timing result.
979 -p<P>: use a precision of <P> digits to display the timing result.
979 Default: 3
980 Default: 3
980
981
981 -q: Quiet, do not print result.
982 -q: Quiet, do not print result.
982
983
983 -o: return a TimeitResult that can be stored in a variable to inspect
984 -o: return a TimeitResult that can be stored in a variable to inspect
984 the result in more details.
985 the result in more details.
985
986
986
987
987 Examples
988 Examples
988 --------
989 --------
989 ::
990 ::
990
991
991 In [1]: %timeit pass
992 In [1]: %timeit pass
992 8.26 ns ± 0.12 ns per loop (mean ± std. dev. of 7 runs, 100000000 loops each)
993 8.26 ns ± 0.12 ns per loop (mean ± std. dev. of 7 runs, 100000000 loops each)
993
994
994 In [2]: u = None
995 In [2]: u = None
995
996
996 In [3]: %timeit u is None
997 In [3]: %timeit u is None
997 29.9 ns ± 0.643 ns per loop (mean ± std. dev. of 7 runs, 10000000 loops each)
998 29.9 ns ± 0.643 ns per loop (mean ± std. dev. of 7 runs, 10000000 loops each)
998
999
999 In [4]: %timeit -r 4 u == None
1000 In [4]: %timeit -r 4 u == None
1000
1001
1001 In [5]: import time
1002 In [5]: import time
1002
1003
1003 In [6]: %timeit -n1 time.sleep(2)
1004 In [6]: %timeit -n1 time.sleep(2)
1004
1005
1005
1006
1006 The times reported by %timeit will be slightly higher than those
1007 The times reported by %timeit will be slightly higher than those
1007 reported by the timeit.py script when variables are accessed. This is
1008 reported by the timeit.py script when variables are accessed. This is
1008 due to the fact that %timeit executes the statement in the namespace
1009 due to the fact that %timeit executes the statement in the namespace
1009 of the shell, compared with timeit.py, which uses a single setup
1010 of the shell, compared with timeit.py, which uses a single setup
1010 statement to import function or create variables. Generally, the bias
1011 statement to import function or create variables. Generally, the bias
1011 does not matter as long as results from timeit.py are not mixed with
1012 does not matter as long as results from timeit.py are not mixed with
1012 those from %timeit."""
1013 those from %timeit."""
1013
1014
1014 opts, stmt = self.parse_options(line,'n:r:tcp:qo',
1015 opts, stmt = self.parse_options(line,'n:r:tcp:qo',
1015 posix=False, strict=False)
1016 posix=False, strict=False)
1016 if stmt == "" and cell is None:
1017 if stmt == "" and cell is None:
1017 return
1018 return
1018
1019
1019 timefunc = timeit.default_timer
1020 timefunc = timeit.default_timer
1020 number = int(getattr(opts, "n", 0))
1021 number = int(getattr(opts, "n", 0))
1021 default_repeat = 7 if timeit.default_repeat < 7 else timeit.default_repeat
1022 default_repeat = 7 if timeit.default_repeat < 7 else timeit.default_repeat
1022 repeat = int(getattr(opts, "r", default_repeat))
1023 repeat = int(getattr(opts, "r", default_repeat))
1023 precision = int(getattr(opts, "p", 3))
1024 precision = int(getattr(opts, "p", 3))
1024 quiet = 'q' in opts
1025 quiet = 'q' in opts
1025 return_result = 'o' in opts
1026 return_result = 'o' in opts
1026 if hasattr(opts, "t"):
1027 if hasattr(opts, "t"):
1027 timefunc = time.time
1028 timefunc = time.time
1028 if hasattr(opts, "c"):
1029 if hasattr(opts, "c"):
1029 timefunc = clock
1030 timefunc = clock
1030
1031
1031 timer = Timer(timer=timefunc)
1032 timer = Timer(timer=timefunc)
1032 # this code has tight coupling to the inner workings of timeit.Timer,
1033 # this code has tight coupling to the inner workings of timeit.Timer,
1033 # but is there a better way to achieve that the code stmt has access
1034 # but is there a better way to achieve that the code stmt has access
1034 # to the shell namespace?
1035 # to the shell namespace?
1035 transform = self.shell.transform_cell
1036 transform = self.shell.transform_cell
1036
1037
1037 if cell is None:
1038 if cell is None:
1038 # called as line magic
1039 # called as line magic
1039 ast_setup = self.shell.compile.ast_parse("pass")
1040 ast_setup = self.shell.compile.ast_parse("pass")
1040 ast_stmt = self.shell.compile.ast_parse(transform(stmt))
1041 ast_stmt = self.shell.compile.ast_parse(transform(stmt))
1041 else:
1042 else:
1042 ast_setup = self.shell.compile.ast_parse(transform(stmt))
1043 ast_setup = self.shell.compile.ast_parse(transform(stmt))
1043 ast_stmt = self.shell.compile.ast_parse(transform(cell))
1044 ast_stmt = self.shell.compile.ast_parse(transform(cell))
1044
1045
1045 ast_setup = self.shell.transform_ast(ast_setup)
1046 ast_setup = self.shell.transform_ast(ast_setup)
1046 ast_stmt = self.shell.transform_ast(ast_stmt)
1047 ast_stmt = self.shell.transform_ast(ast_stmt)
1047
1048
1048 # Check that these compile to valid Python code *outside* the timer func
1049 # Check that these compile to valid Python code *outside* the timer func
1049 # Invalid code may become valid when put inside the function & loop,
1050 # Invalid code may become valid when put inside the function & loop,
1050 # which messes up error messages.
1051 # which messes up error messages.
1051 # https://github.com/ipython/ipython/issues/10636
1052 # https://github.com/ipython/ipython/issues/10636
1052 self.shell.compile(ast_setup, "<magic-timeit-setup>", "exec")
1053 self.shell.compile(ast_setup, "<magic-timeit-setup>", "exec")
1053 self.shell.compile(ast_stmt, "<magic-timeit-stmt>", "exec")
1054 self.shell.compile(ast_stmt, "<magic-timeit-stmt>", "exec")
1054
1055
1055 # This codestring is taken from timeit.template - we fill it in as an
1056 # This codestring is taken from timeit.template - we fill it in as an
1056 # AST, so that we can apply our AST transformations to the user code
1057 # AST, so that we can apply our AST transformations to the user code
1057 # without affecting the timing code.
1058 # without affecting the timing code.
1058 timeit_ast_template = ast.parse('def inner(_it, _timer):\n'
1059 timeit_ast_template = ast.parse('def inner(_it, _timer):\n'
1059 ' setup\n'
1060 ' setup\n'
1060 ' _t0 = _timer()\n'
1061 ' _t0 = _timer()\n'
1061 ' for _i in _it:\n'
1062 ' for _i in _it:\n'
1062 ' stmt\n'
1063 ' stmt\n'
1063 ' _t1 = _timer()\n'
1064 ' _t1 = _timer()\n'
1064 ' return _t1 - _t0\n')
1065 ' return _t1 - _t0\n')
1065
1066
1066 timeit_ast = TimeitTemplateFiller(ast_setup, ast_stmt).visit(timeit_ast_template)
1067 timeit_ast = TimeitTemplateFiller(ast_setup, ast_stmt).visit(timeit_ast_template)
1067 timeit_ast = ast.fix_missing_locations(timeit_ast)
1068 timeit_ast = ast.fix_missing_locations(timeit_ast)
1068
1069
1069 # Track compilation time so it can be reported if too long
1070 # Track compilation time so it can be reported if too long
1070 # Minimum time above which compilation time will be reported
1071 # Minimum time above which compilation time will be reported
1071 tc_min = 0.1
1072 tc_min = 0.1
1072
1073
1073 t0 = clock()
1074 t0 = clock()
1074 code = self.shell.compile(timeit_ast, "<magic-timeit>", "exec")
1075 code = self.shell.compile(timeit_ast, "<magic-timeit>", "exec")
1075 tc = clock()-t0
1076 tc = clock()-t0
1076
1077
1077 ns = {}
1078 ns = {}
1078 glob = self.shell.user_ns
1079 glob = self.shell.user_ns
1079 # handles global vars with same name as local vars. We store them in conflict_globs.
1080 # handles global vars with same name as local vars. We store them in conflict_globs.
1080 if local_ns is not None:
1081 if local_ns is not None:
1081 conflict_globs = {}
1082 conflict_globs = {}
1082 for var_name, var_val in glob.items():
1083 for var_name, var_val in glob.items():
1083 if var_name in local_ns:
1084 if var_name in local_ns:
1084 conflict_globs[var_name] = var_val
1085 conflict_globs[var_name] = var_val
1085 glob.update(local_ns)
1086 glob.update(local_ns)
1086
1087
1087 exec(code, glob, ns)
1088 exec(code, glob, ns)
1088 timer.inner = ns["inner"]
1089 timer.inner = ns["inner"]
1089
1090
1090 # This is used to check if there is a huge difference between the
1091 # This is used to check if there is a huge difference between the
1091 # best and worst timings.
1092 # best and worst timings.
1092 # Issue: https://github.com/ipython/ipython/issues/6471
1093 # Issue: https://github.com/ipython/ipython/issues/6471
1093 if number == 0:
1094 if number == 0:
1094 # determine number so that 0.2 <= total time < 2.0
1095 # determine number so that 0.2 <= total time < 2.0
1095 for index in range(0, 10):
1096 for index in range(0, 10):
1096 number = 10 ** index
1097 number = 10 ** index
1097 time_number = timer.timeit(number)
1098 time_number = timer.timeit(number)
1098 if time_number >= 0.2:
1099 if time_number >= 0.2:
1099 break
1100 break
1100
1101
1101 all_runs = timer.repeat(repeat, number)
1102 all_runs = timer.repeat(repeat, number)
1102 best = min(all_runs) / number
1103 best = min(all_runs) / number
1103 worst = max(all_runs) / number
1104 worst = max(all_runs) / number
1104 timeit_result = TimeitResult(number, repeat, best, worst, all_runs, tc, precision)
1105 timeit_result = TimeitResult(number, repeat, best, worst, all_runs, tc, precision)
1105
1106
1106 # Restore global vars from conflict_globs
1107 # Restore global vars from conflict_globs
1107 if local_ns is not None:
1108 if local_ns is not None:
1108 if len(conflict_globs) > 0:
1109 if len(conflict_globs) > 0:
1109 glob.update(conflict_globs)
1110 glob.update(conflict_globs)
1110
1111
1111 if not quiet :
1112 if not quiet :
1112 # Check best timing is greater than zero to avoid a
1113 # Check best timing is greater than zero to avoid a
1113 # ZeroDivisionError.
1114 # ZeroDivisionError.
1114 # In cases where the slowest timing is lesser than a micosecond
1115 # In cases where the slowest timing is lesser than a micosecond
1115 # we assume that it does not really matter if the fastest
1116 # we assume that it does not really matter if the fastest
1116 # timing is 4 times faster than the slowest timing or not.
1117 # timing is 4 times faster than the slowest timing or not.
1117 if worst > 4 * best and best > 0 and worst > 1e-6:
1118 if worst > 4 * best and best > 0 and worst > 1e-6:
1118 print("The slowest run took %0.2f times longer than the "
1119 print("The slowest run took %0.2f times longer than the "
1119 "fastest. This could mean that an intermediate result "
1120 "fastest. This could mean that an intermediate result "
1120 "is being cached." % (worst / best))
1121 "is being cached." % (worst / best))
1121
1122
1122 print( timeit_result )
1123 print( timeit_result )
1123
1124
1124 if tc > tc_min:
1125 if tc > tc_min:
1125 print("Compiler time: %.2f s" % tc)
1126 print("Compiler time: %.2f s" % tc)
1126 if return_result:
1127 if return_result:
1127 return timeit_result
1128 return timeit_result
1128
1129
1129 @skip_doctest
1130 @skip_doctest
1130 @needs_local_scope
1131 @needs_local_scope
1131 @line_cell_magic
1132 @line_cell_magic
1132 def time(self,line='', cell=None, local_ns=None):
1133 def time(self,line='', cell=None, local_ns=None):
1133 """Time execution of a Python statement or expression.
1134 """Time execution of a Python statement or expression.
1134
1135
1135 The CPU and wall clock times are printed, and the value of the
1136 The CPU and wall clock times are printed, and the value of the
1136 expression (if any) is returned. Note that under Win32, system time
1137 expression (if any) is returned. Note that under Win32, system time
1137 is always reported as 0, since it can not be measured.
1138 is always reported as 0, since it can not be measured.
1138
1139
1139 This function can be used both as a line and cell magic:
1140 This function can be used both as a line and cell magic:
1140
1141
1141 - In line mode you can time a single-line statement (though multiple
1142 - In line mode you can time a single-line statement (though multiple
1142 ones can be chained with using semicolons).
1143 ones can be chained with using semicolons).
1143
1144
1144 - In cell mode, you can time the cell body (a directly
1145 - In cell mode, you can time the cell body (a directly
1145 following statement raises an error).
1146 following statement raises an error).
1146
1147
1147 This function provides very basic timing functionality. Use the timeit
1148 This function provides very basic timing functionality. Use the timeit
1148 magic for more control over the measurement.
1149 magic for more control over the measurement.
1149
1150
1150 Examples
1151 Examples
1151 --------
1152 --------
1152 ::
1153 ::
1153
1154
1154 In [1]: %time 2**128
1155 In [1]: %time 2**128
1155 CPU times: user 0.00 s, sys: 0.00 s, total: 0.00 s
1156 CPU times: user 0.00 s, sys: 0.00 s, total: 0.00 s
1156 Wall time: 0.00
1157 Wall time: 0.00
1157 Out[1]: 340282366920938463463374607431768211456L
1158 Out[1]: 340282366920938463463374607431768211456L
1158
1159
1159 In [2]: n = 1000000
1160 In [2]: n = 1000000
1160
1161
1161 In [3]: %time sum(range(n))
1162 In [3]: %time sum(range(n))
1162 CPU times: user 1.20 s, sys: 0.05 s, total: 1.25 s
1163 CPU times: user 1.20 s, sys: 0.05 s, total: 1.25 s
1163 Wall time: 1.37
1164 Wall time: 1.37
1164 Out[3]: 499999500000L
1165 Out[3]: 499999500000L
1165
1166
1166 In [4]: %time print 'hello world'
1167 In [4]: %time print 'hello world'
1167 hello world
1168 hello world
1168 CPU times: user 0.00 s, sys: 0.00 s, total: 0.00 s
1169 CPU times: user 0.00 s, sys: 0.00 s, total: 0.00 s
1169 Wall time: 0.00
1170 Wall time: 0.00
1170
1171
1171 Note that the time needed by Python to compile the given expression
1172 Note that the time needed by Python to compile the given expression
1172 will be reported if it is more than 0.1s. In this example, the
1173 will be reported if it is more than 0.1s. In this example, the
1173 actual exponentiation is done by Python at compilation time, so while
1174 actual exponentiation is done by Python at compilation time, so while
1174 the expression can take a noticeable amount of time to compute, that
1175 the expression can take a noticeable amount of time to compute, that
1175 time is purely due to the compilation:
1176 time is purely due to the compilation:
1176
1177
1177 In [5]: %time 3**9999;
1178 In [5]: %time 3**9999;
1178 CPU times: user 0.00 s, sys: 0.00 s, total: 0.00 s
1179 CPU times: user 0.00 s, sys: 0.00 s, total: 0.00 s
1179 Wall time: 0.00 s
1180 Wall time: 0.00 s
1180
1181
1181 In [6]: %time 3**999999;
1182 In [6]: %time 3**999999;
1182 CPU times: user 0.00 s, sys: 0.00 s, total: 0.00 s
1183 CPU times: user 0.00 s, sys: 0.00 s, total: 0.00 s
1183 Wall time: 0.00 s
1184 Wall time: 0.00 s
1184 Compiler : 0.78 s
1185 Compiler : 0.78 s
1185 """
1186 """
1186
1187
1187 # fail immediately if the given expression can't be compiled
1188 # fail immediately if the given expression can't be compiled
1188
1189
1189 if line and cell:
1190 if line and cell:
1190 raise UsageError("Can't use statement directly after '%%time'!")
1191 raise UsageError("Can't use statement directly after '%%time'!")
1191
1192
1192 if cell:
1193 if cell:
1193 expr = self.shell.transform_cell(cell)
1194 expr = self.shell.transform_cell(cell)
1194 else:
1195 else:
1195 expr = self.shell.transform_cell(line)
1196 expr = self.shell.transform_cell(line)
1196
1197
1197 # Minimum time above which parse time will be reported
1198 # Minimum time above which parse time will be reported
1198 tp_min = 0.1
1199 tp_min = 0.1
1199
1200
1200 t0 = clock()
1201 t0 = clock()
1201 expr_ast = self.shell.compile.ast_parse(expr)
1202 expr_ast = self.shell.compile.ast_parse(expr)
1202 tp = clock()-t0
1203 tp = clock()-t0
1203
1204
1204 # Apply AST transformations
1205 # Apply AST transformations
1205 expr_ast = self.shell.transform_ast(expr_ast)
1206 expr_ast = self.shell.transform_ast(expr_ast)
1206
1207
1207 # Minimum time above which compilation time will be reported
1208 # Minimum time above which compilation time will be reported
1208 tc_min = 0.1
1209 tc_min = 0.1
1209
1210
1210 if len(expr_ast.body)==1 and isinstance(expr_ast.body[0], ast.Expr):
1211 if len(expr_ast.body)==1 and isinstance(expr_ast.body[0], ast.Expr):
1211 mode = 'eval'
1212 mode = 'eval'
1212 source = '<timed eval>'
1213 source = '<timed eval>'
1213 expr_ast = ast.Expression(expr_ast.body[0].value)
1214 expr_ast = ast.Expression(expr_ast.body[0].value)
1214 else:
1215 else:
1215 mode = 'exec'
1216 mode = 'exec'
1216 source = '<timed exec>'
1217 source = '<timed exec>'
1217 t0 = clock()
1218 t0 = clock()
1218 code = self.shell.compile(expr_ast, source, mode)
1219 code = self.shell.compile(expr_ast, source, mode)
1219 tc = clock()-t0
1220 tc = clock()-t0
1220
1221
1221 # skew measurement as little as possible
1222 # skew measurement as little as possible
1222 glob = self.shell.user_ns
1223 glob = self.shell.user_ns
1223 wtime = time.time
1224 wtime = time.time
1224 # time execution
1225 # time execution
1225 wall_st = wtime()
1226 wall_st = wtime()
1226 if mode=='eval':
1227 if mode=='eval':
1227 st = clock2()
1228 st = clock2()
1228 try:
1229 try:
1229 out = eval(code, glob, local_ns)
1230 out = eval(code, glob, local_ns)
1230 except:
1231 except:
1231 self.shell.showtraceback()
1232 self.shell.showtraceback()
1232 return
1233 return
1233 end = clock2()
1234 end = clock2()
1234 else:
1235 else:
1235 st = clock2()
1236 st = clock2()
1236 try:
1237 try:
1237 exec(code, glob, local_ns)
1238 exec(code, glob, local_ns)
1238 except:
1239 except:
1239 self.shell.showtraceback()
1240 self.shell.showtraceback()
1240 return
1241 return
1241 end = clock2()
1242 end = clock2()
1242 out = None
1243 out = None
1243 wall_end = wtime()
1244 wall_end = wtime()
1244 # Compute actual times and report
1245 # Compute actual times and report
1245 wall_time = wall_end-wall_st
1246 wall_time = wall_end-wall_st
1246 cpu_user = end[0]-st[0]
1247 cpu_user = end[0]-st[0]
1247 cpu_sys = end[1]-st[1]
1248 cpu_sys = end[1]-st[1]
1248 cpu_tot = cpu_user+cpu_sys
1249 cpu_tot = cpu_user+cpu_sys
1249 # On windows cpu_sys is always zero, so no new information to the next print
1250 # On windows cpu_sys is always zero, so no new information to the next print
1250 if sys.platform != 'win32':
1251 if sys.platform != 'win32':
1251 print("CPU times: user %s, sys: %s, total: %s" % \
1252 print("CPU times: user %s, sys: %s, total: %s" % \
1252 (_format_time(cpu_user),_format_time(cpu_sys),_format_time(cpu_tot)))
1253 (_format_time(cpu_user),_format_time(cpu_sys),_format_time(cpu_tot)))
1253 print("Wall time: %s" % _format_time(wall_time))
1254 print("Wall time: %s" % _format_time(wall_time))
1254 if tc > tc_min:
1255 if tc > tc_min:
1255 print("Compiler : %s" % _format_time(tc))
1256 print("Compiler : %s" % _format_time(tc))
1256 if tp > tp_min:
1257 if tp > tp_min:
1257 print("Parser : %s" % _format_time(tp))
1258 print("Parser : %s" % _format_time(tp))
1258 return out
1259 return out
1259
1260
1260 @skip_doctest
1261 @skip_doctest
1261 @line_magic
1262 @line_magic
1262 def macro(self, parameter_s=''):
1263 def macro(self, parameter_s=''):
1263 """Define a macro for future re-execution. It accepts ranges of history,
1264 """Define a macro for future re-execution. It accepts ranges of history,
1264 filenames or string objects.
1265 filenames or string objects.
1265
1266
1266 Usage:\\
1267 Usage:\\
1267 %macro [options] name n1-n2 n3-n4 ... n5 .. n6 ...
1268 %macro [options] name n1-n2 n3-n4 ... n5 .. n6 ...
1268
1269
1269 Options:
1270 Options:
1270
1271
1271 -r: use 'raw' input. By default, the 'processed' history is used,
1272 -r: use 'raw' input. By default, the 'processed' history is used,
1272 so that magics are loaded in their transformed version to valid
1273 so that magics are loaded in their transformed version to valid
1273 Python. If this option is given, the raw input as typed at the
1274 Python. If this option is given, the raw input as typed at the
1274 command line is used instead.
1275 command line is used instead.
1275
1276
1276 -q: quiet macro definition. By default, a tag line is printed
1277 -q: quiet macro definition. By default, a tag line is printed
1277 to indicate the macro has been created, and then the contents of
1278 to indicate the macro has been created, and then the contents of
1278 the macro are printed. If this option is given, then no printout
1279 the macro are printed. If this option is given, then no printout
1279 is produced once the macro is created.
1280 is produced once the macro is created.
1280
1281
1281 This will define a global variable called `name` which is a string
1282 This will define a global variable called `name` which is a string
1282 made of joining the slices and lines you specify (n1,n2,... numbers
1283 made of joining the slices and lines you specify (n1,n2,... numbers
1283 above) from your input history into a single string. This variable
1284 above) from your input history into a single string. This variable
1284 acts like an automatic function which re-executes those lines as if
1285 acts like an automatic function which re-executes those lines as if
1285 you had typed them. You just type 'name' at the prompt and the code
1286 you had typed them. You just type 'name' at the prompt and the code
1286 executes.
1287 executes.
1287
1288
1288 The syntax for indicating input ranges is described in %history.
1289 The syntax for indicating input ranges is described in %history.
1289
1290
1290 Note: as a 'hidden' feature, you can also use traditional python slice
1291 Note: as a 'hidden' feature, you can also use traditional python slice
1291 notation, where N:M means numbers N through M-1.
1292 notation, where N:M means numbers N through M-1.
1292
1293
1293 For example, if your history contains (print using %hist -n )::
1294 For example, if your history contains (print using %hist -n )::
1294
1295
1295 44: x=1
1296 44: x=1
1296 45: y=3
1297 45: y=3
1297 46: z=x+y
1298 46: z=x+y
1298 47: print x
1299 47: print x
1299 48: a=5
1300 48: a=5
1300 49: print 'x',x,'y',y
1301 49: print 'x',x,'y',y
1301
1302
1302 you can create a macro with lines 44 through 47 (included) and line 49
1303 you can create a macro with lines 44 through 47 (included) and line 49
1303 called my_macro with::
1304 called my_macro with::
1304
1305
1305 In [55]: %macro my_macro 44-47 49
1306 In [55]: %macro my_macro 44-47 49
1306
1307
1307 Now, typing `my_macro` (without quotes) will re-execute all this code
1308 Now, typing `my_macro` (without quotes) will re-execute all this code
1308 in one pass.
1309 in one pass.
1309
1310
1310 You don't need to give the line-numbers in order, and any given line
1311 You don't need to give the line-numbers in order, and any given line
1311 number can appear multiple times. You can assemble macros with any
1312 number can appear multiple times. You can assemble macros with any
1312 lines from your input history in any order.
1313 lines from your input history in any order.
1313
1314
1314 The macro is a simple object which holds its value in an attribute,
1315 The macro is a simple object which holds its value in an attribute,
1315 but IPython's display system checks for macros and executes them as
1316 but IPython's display system checks for macros and executes them as
1316 code instead of printing them when you type their name.
1317 code instead of printing them when you type their name.
1317
1318
1318 You can view a macro's contents by explicitly printing it with::
1319 You can view a macro's contents by explicitly printing it with::
1319
1320
1320 print macro_name
1321 print macro_name
1321
1322
1322 """
1323 """
1323 opts,args = self.parse_options(parameter_s,'rq',mode='list')
1324 opts,args = self.parse_options(parameter_s,'rq',mode='list')
1324 if not args: # List existing macros
1325 if not args: # List existing macros
1325 return sorted(k for k,v in self.shell.user_ns.items() if isinstance(v, Macro))
1326 return sorted(k for k,v in self.shell.user_ns.items() if isinstance(v, Macro))
1326 if len(args) == 1:
1327 if len(args) == 1:
1327 raise UsageError(
1328 raise UsageError(
1328 "%macro insufficient args; usage '%macro name n1-n2 n3-4...")
1329 "%macro insufficient args; usage '%macro name n1-n2 n3-4...")
1329 name, codefrom = args[0], " ".join(args[1:])
1330 name, codefrom = args[0], " ".join(args[1:])
1330
1331
1331 #print 'rng',ranges # dbg
1332 #print 'rng',ranges # dbg
1332 try:
1333 try:
1333 lines = self.shell.find_user_code(codefrom, 'r' in opts)
1334 lines = self.shell.find_user_code(codefrom, 'r' in opts)
1334 except (ValueError, TypeError) as e:
1335 except (ValueError, TypeError) as e:
1335 print(e.args[0])
1336 print(e.args[0])
1336 return
1337 return
1337 macro = Macro(lines)
1338 macro = Macro(lines)
1338 self.shell.define_macro(name, macro)
1339 self.shell.define_macro(name, macro)
1339 if not ( 'q' in opts) :
1340 if not ( 'q' in opts) :
1340 print('Macro `%s` created. To execute, type its name (without quotes).' % name)
1341 print('Macro `%s` created. To execute, type its name (without quotes).' % name)
1341 print('=== Macro contents: ===')
1342 print('=== Macro contents: ===')
1342 print(macro, end=' ')
1343 print(macro, end=' ')
1343
1344
1344 @magic_arguments.magic_arguments()
1345 @magic_arguments.magic_arguments()
1345 @magic_arguments.argument('output', type=str, default='', nargs='?',
1346 @magic_arguments.argument('output', type=str, default='', nargs='?',
1346 help="""The name of the variable in which to store output.
1347 help="""The name of the variable in which to store output.
1347 This is a utils.io.CapturedIO object with stdout/err attributes
1348 This is a utils.io.CapturedIO object with stdout/err attributes
1348 for the text of the captured output.
1349 for the text of the captured output.
1349
1350
1350 CapturedOutput also has a show() method for displaying the output,
1351 CapturedOutput also has a show() method for displaying the output,
1351 and __call__ as well, so you can use that to quickly display the
1352 and __call__ as well, so you can use that to quickly display the
1352 output.
1353 output.
1353
1354
1354 If unspecified, captured output is discarded.
1355 If unspecified, captured output is discarded.
1355 """
1356 """
1356 )
1357 )
1357 @magic_arguments.argument('--no-stderr', action="store_true",
1358 @magic_arguments.argument('--no-stderr', action="store_true",
1358 help="""Don't capture stderr."""
1359 help="""Don't capture stderr."""
1359 )
1360 )
1360 @magic_arguments.argument('--no-stdout', action="store_true",
1361 @magic_arguments.argument('--no-stdout', action="store_true",
1361 help="""Don't capture stdout."""
1362 help="""Don't capture stdout."""
1362 )
1363 )
1363 @magic_arguments.argument('--no-display', action="store_true",
1364 @magic_arguments.argument('--no-display', action="store_true",
1364 help="""Don't capture IPython's rich display."""
1365 help="""Don't capture IPython's rich display."""
1365 )
1366 )
1366 @cell_magic
1367 @cell_magic
1367 def capture(self, line, cell):
1368 def capture(self, line, cell):
1368 """run the cell, capturing stdout, stderr, and IPython's rich display() calls."""
1369 """run the cell, capturing stdout, stderr, and IPython's rich display() calls."""
1369 args = magic_arguments.parse_argstring(self.capture, line)
1370 args = magic_arguments.parse_argstring(self.capture, line)
1370 out = not args.no_stdout
1371 out = not args.no_stdout
1371 err = not args.no_stderr
1372 err = not args.no_stderr
1372 disp = not args.no_display
1373 disp = not args.no_display
1373 with capture_output(out, err, disp) as io:
1374 with capture_output(out, err, disp) as io:
1374 self.shell.run_cell(cell)
1375 self.shell.run_cell(cell)
1375 if args.output:
1376 if args.output:
1376 self.shell.user_ns[args.output] = io
1377 self.shell.user_ns[args.output] = io
1377
1378
1378 def parse_breakpoint(text, current_file):
1379 def parse_breakpoint(text, current_file):
1379 '''Returns (file, line) for file:line and (current_file, line) for line'''
1380 '''Returns (file, line) for file:line and (current_file, line) for line'''
1380 colon = text.find(':')
1381 colon = text.find(':')
1381 if colon == -1:
1382 if colon == -1:
1382 return current_file, int(text)
1383 return current_file, int(text)
1383 else:
1384 else:
1384 return text[:colon], int(text[colon+1:])
1385 return text[:colon], int(text[colon+1:])
1385
1386
1386 def _format_time(timespan, precision=3):
1387 def _format_time(timespan, precision=3):
1387 """Formats the timespan in a human readable form"""
1388 """Formats the timespan in a human readable form"""
1388
1389
1389 if timespan >= 60.0:
1390 if timespan >= 60.0:
1390 # we have more than a minute, format that in a human readable form
1391 # we have more than a minute, format that in a human readable form
1391 # Idea from http://snipplr.com/view/5713/
1392 # Idea from http://snipplr.com/view/5713/
1392 parts = [("d", 60*60*24),("h", 60*60),("min", 60), ("s", 1)]
1393 parts = [("d", 60*60*24),("h", 60*60),("min", 60), ("s", 1)]
1393 time = []
1394 time = []
1394 leftover = timespan
1395 leftover = timespan
1395 for suffix, length in parts:
1396 for suffix, length in parts:
1396 value = int(leftover / length)
1397 value = int(leftover / length)
1397 if value > 0:
1398 if value > 0:
1398 leftover = leftover % length
1399 leftover = leftover % length
1399 time.append(u'%s%s' % (str(value), suffix))
1400 time.append(u'%s%s' % (str(value), suffix))
1400 if leftover < 1:
1401 if leftover < 1:
1401 break
1402 break
1402 return " ".join(time)
1403 return " ".join(time)
1403
1404
1404
1405
1405 # Unfortunately the unicode 'micro' symbol can cause problems in
1406 # Unfortunately the unicode 'micro' symbol can cause problems in
1406 # certain terminals.
1407 # certain terminals.
1407 # See bug: https://bugs.launchpad.net/ipython/+bug/348466
1408 # See bug: https://bugs.launchpad.net/ipython/+bug/348466
1408 # Try to prevent crashes by being more secure than it needs to
1409 # Try to prevent crashes by being more secure than it needs to
1409 # E.g. eclipse is able to print a µ, but has no sys.stdout.encoding set.
1410 # E.g. eclipse is able to print a µ, but has no sys.stdout.encoding set.
1410 units = [u"s", u"ms",u'us',"ns"] # the save value
1411 units = [u"s", u"ms",u'us',"ns"] # the save value
1411 if hasattr(sys.stdout, 'encoding') and sys.stdout.encoding:
1412 if hasattr(sys.stdout, 'encoding') and sys.stdout.encoding:
1412 try:
1413 try:
1413 u'\xb5'.encode(sys.stdout.encoding)
1414 u'\xb5'.encode(sys.stdout.encoding)
1414 units = [u"s", u"ms",u'\xb5s',"ns"]
1415 units = [u"s", u"ms",u'\xb5s',"ns"]
1415 except:
1416 except:
1416 pass
1417 pass
1417 scaling = [1, 1e3, 1e6, 1e9]
1418 scaling = [1, 1e3, 1e6, 1e9]
1418
1419
1419 if timespan > 0.0:
1420 if timespan > 0.0:
1420 order = min(-int(math.floor(math.log10(timespan)) // 3), 3)
1421 order = min(-int(math.floor(math.log10(timespan)) // 3), 3)
1421 else:
1422 else:
1422 order = 3
1423 order = 3
1423 return u"%.*g %s" % (precision, timespan * scaling[order], units[order])
1424 return u"%.*g %s" % (precision, timespan * scaling[order], units[order])
@@ -1,286 +1,294 b''
1 """Magic functions for running cells in various scripts."""
1 """Magic functions for running cells in various scripts."""
2
2
3 # Copyright (c) IPython Development Team.
3 # Copyright (c) IPython Development Team.
4 # Distributed under the terms of the Modified BSD License.
4 # Distributed under the terms of the Modified BSD License.
5
5
6 import errno
6 import errno
7 import os
7 import os
8 import sys
8 import sys
9 import signal
9 import signal
10 import time
10 import time
11 from subprocess import Popen, PIPE
11 from subprocess import Popen, PIPE, CalledProcessError
12 import atexit
12 import atexit
13
13
14 from IPython.core import magic_arguments
14 from IPython.core import magic_arguments
15 from IPython.core.magic import (
15 from IPython.core.magic import (
16 Magics, magics_class, line_magic, cell_magic
16 Magics, magics_class, line_magic, cell_magic
17 )
17 )
18 from IPython.lib.backgroundjobs import BackgroundJobManager
18 from IPython.lib.backgroundjobs import BackgroundJobManager
19 from IPython.utils import py3compat
19 from IPython.utils import py3compat
20 from IPython.utils.process import arg_split
20 from IPython.utils.process import arg_split
21 from traitlets import List, Dict, default
21 from traitlets import List, Dict, default
22
22
23 #-----------------------------------------------------------------------------
23 #-----------------------------------------------------------------------------
24 # Magic implementation classes
24 # Magic implementation classes
25 #-----------------------------------------------------------------------------
25 #-----------------------------------------------------------------------------
26
26
27 def script_args(f):
27 def script_args(f):
28 """single decorator for adding script args"""
28 """single decorator for adding script args"""
29 args = [
29 args = [
30 magic_arguments.argument(
30 magic_arguments.argument(
31 '--out', type=str,
31 '--out', type=str,
32 help="""The variable in which to store stdout from the script.
32 help="""The variable in which to store stdout from the script.
33 If the script is backgrounded, this will be the stdout *pipe*,
33 If the script is backgrounded, this will be the stdout *pipe*,
34 instead of the stderr text itself and will not be auto closed.
34 instead of the stderr text itself and will not be auto closed.
35 """
35 """
36 ),
36 ),
37 magic_arguments.argument(
37 magic_arguments.argument(
38 '--err', type=str,
38 '--err', type=str,
39 help="""The variable in which to store stderr from the script.
39 help="""The variable in which to store stderr from the script.
40 If the script is backgrounded, this will be the stderr *pipe*,
40 If the script is backgrounded, this will be the stderr *pipe*,
41 instead of the stderr text itself and will not be autoclosed.
41 instead of the stderr text itself and will not be autoclosed.
42 """
42 """
43 ),
43 ),
44 magic_arguments.argument(
44 magic_arguments.argument(
45 '--bg', action="store_true",
45 '--bg', action="store_true",
46 help="""Whether to run the script in the background.
46 help="""Whether to run the script in the background.
47 If given, the only way to see the output of the command is
47 If given, the only way to see the output of the command is
48 with --out/err.
48 with --out/err.
49 """
49 """
50 ),
50 ),
51 magic_arguments.argument(
51 magic_arguments.argument(
52 '--proc', type=str,
52 '--proc', type=str,
53 help="""The variable in which to store Popen instance.
53 help="""The variable in which to store Popen instance.
54 This is used only when --bg option is given.
54 This is used only when --bg option is given.
55 """
55 """
56 ),
56 ),
57 magic_arguments.argument(
58 '--raise-error', action="store_true",
59 help="""Whether you should raise an error message in addition to
60 a stream on stderr if you get a nonzero exit code.
61 """
62 )
57 ]
63 ]
58 for arg in args:
64 for arg in args:
59 f = arg(f)
65 f = arg(f)
60 return f
66 return f
61
67
62 @magics_class
68 @magics_class
63 class ScriptMagics(Magics):
69 class ScriptMagics(Magics):
64 """Magics for talking to scripts
70 """Magics for talking to scripts
65
71
66 This defines a base `%%script` cell magic for running a cell
72 This defines a base `%%script` cell magic for running a cell
67 with a program in a subprocess, and registers a few top-level
73 with a program in a subprocess, and registers a few top-level
68 magics that call %%script with common interpreters.
74 magics that call %%script with common interpreters.
69 """
75 """
70 script_magics = List(
76 script_magics = List(
71 help="""Extra script cell magics to define
77 help="""Extra script cell magics to define
72
78
73 This generates simple wrappers of `%%script foo` as `%%foo`.
79 This generates simple wrappers of `%%script foo` as `%%foo`.
74
80
75 If you want to add script magics that aren't on your path,
81 If you want to add script magics that aren't on your path,
76 specify them in script_paths
82 specify them in script_paths
77 """,
83 """,
78 ).tag(config=True)
84 ).tag(config=True)
79 @default('script_magics')
85 @default('script_magics')
80 def _script_magics_default(self):
86 def _script_magics_default(self):
81 """default to a common list of programs"""
87 """default to a common list of programs"""
82
88
83 defaults = [
89 defaults = [
84 'sh',
90 'sh',
85 'bash',
91 'bash',
86 'perl',
92 'perl',
87 'ruby',
93 'ruby',
88 'python',
94 'python',
89 'python2',
95 'python2',
90 'python3',
96 'python3',
91 'pypy',
97 'pypy',
92 ]
98 ]
93 if os.name == 'nt':
99 if os.name == 'nt':
94 defaults.extend([
100 defaults.extend([
95 'cmd',
101 'cmd',
96 ])
102 ])
97
103
98 return defaults
104 return defaults
99
105
100 script_paths = Dict(
106 script_paths = Dict(
101 help="""Dict mapping short 'ruby' names to full paths, such as '/opt/secret/bin/ruby'
107 help="""Dict mapping short 'ruby' names to full paths, such as '/opt/secret/bin/ruby'
102
108
103 Only necessary for items in script_magics where the default path will not
109 Only necessary for items in script_magics where the default path will not
104 find the right interpreter.
110 find the right interpreter.
105 """
111 """
106 ).tag(config=True)
112 ).tag(config=True)
107
113
108 def __init__(self, shell=None):
114 def __init__(self, shell=None):
109 super(ScriptMagics, self).__init__(shell=shell)
115 super(ScriptMagics, self).__init__(shell=shell)
110 self._generate_script_magics()
116 self._generate_script_magics()
111 self.job_manager = BackgroundJobManager()
117 self.job_manager = BackgroundJobManager()
112 self.bg_processes = []
118 self.bg_processes = []
113 atexit.register(self.kill_bg_processes)
119 atexit.register(self.kill_bg_processes)
114
120
115 def __del__(self):
121 def __del__(self):
116 self.kill_bg_processes()
122 self.kill_bg_processes()
117
123
118 def _generate_script_magics(self):
124 def _generate_script_magics(self):
119 cell_magics = self.magics['cell']
125 cell_magics = self.magics['cell']
120 for name in self.script_magics:
126 for name in self.script_magics:
121 cell_magics[name] = self._make_script_magic(name)
127 cell_magics[name] = self._make_script_magic(name)
122
128
123 def _make_script_magic(self, name):
129 def _make_script_magic(self, name):
124 """make a named magic, that calls %%script with a particular program"""
130 """make a named magic, that calls %%script with a particular program"""
125 # expand to explicit path if necessary:
131 # expand to explicit path if necessary:
126 script = self.script_paths.get(name, name)
132 script = self.script_paths.get(name, name)
127
133
128 @magic_arguments.magic_arguments()
134 @magic_arguments.magic_arguments()
129 @script_args
135 @script_args
130 def named_script_magic(line, cell):
136 def named_script_magic(line, cell):
131 # if line, add it as cl-flags
137 # if line, add it as cl-flags
132 if line:
138 if line:
133 line = "%s %s" % (script, line)
139 line = "%s %s" % (script, line)
134 else:
140 else:
135 line = script
141 line = script
136 return self.shebang(line, cell)
142 return self.shebang(line, cell)
137
143
138 # write a basic docstring:
144 # write a basic docstring:
139 named_script_magic.__doc__ = \
145 named_script_magic.__doc__ = \
140 """%%{name} script magic
146 """%%{name} script magic
141
147
142 Run cells with {script} in a subprocess.
148 Run cells with {script} in a subprocess.
143
149
144 This is a shortcut for `%%script {script}`
150 This is a shortcut for `%%script {script}`
145 """.format(**locals())
151 """.format(**locals())
146
152
147 return named_script_magic
153 return named_script_magic
148
154
149 @magic_arguments.magic_arguments()
155 @magic_arguments.magic_arguments()
150 @script_args
156 @script_args
151 @cell_magic("script")
157 @cell_magic("script")
152 def shebang(self, line, cell):
158 def shebang(self, line, cell):
153 """Run a cell via a shell command
159 """Run a cell via a shell command
154
160
155 The `%%script` line is like the #! line of script,
161 The `%%script` line is like the #! line of script,
156 specifying a program (bash, perl, ruby, etc.) with which to run.
162 specifying a program (bash, perl, ruby, etc.) with which to run.
157
163
158 The rest of the cell is run by that program.
164 The rest of the cell is run by that program.
159
165
160 Examples
166 Examples
161 --------
167 --------
162 ::
168 ::
163
169
164 In [1]: %%script bash
170 In [1]: %%script bash
165 ...: for i in 1 2 3; do
171 ...: for i in 1 2 3; do
166 ...: echo $i
172 ...: echo $i
167 ...: done
173 ...: done
168 1
174 1
169 2
175 2
170 3
176 3
171 """
177 """
172 argv = arg_split(line, posix = not sys.platform.startswith('win'))
178 argv = arg_split(line, posix = not sys.platform.startswith('win'))
173 args, cmd = self.shebang.parser.parse_known_args(argv)
179 args, cmd = self.shebang.parser.parse_known_args(argv)
174
180
175 try:
181 try:
176 p = Popen(cmd, stdout=PIPE, stderr=PIPE, stdin=PIPE)
182 p = Popen(cmd, stdout=PIPE, stderr=PIPE, stdin=PIPE)
177 except OSError as e:
183 except OSError as e:
178 if e.errno == errno.ENOENT:
184 if e.errno == errno.ENOENT:
179 print("Couldn't find program: %r" % cmd[0])
185 print("Couldn't find program: %r" % cmd[0])
180 return
186 return
181 else:
187 else:
182 raise
188 raise
183
189
184 if not cell.endswith('\n'):
190 if not cell.endswith('\n'):
185 cell += '\n'
191 cell += '\n'
186 cell = cell.encode('utf8', 'replace')
192 cell = cell.encode('utf8', 'replace')
187 if args.bg:
193 if args.bg:
188 self.bg_processes.append(p)
194 self.bg_processes.append(p)
189 self._gc_bg_processes()
195 self._gc_bg_processes()
190 to_close = []
196 to_close = []
191 if args.out:
197 if args.out:
192 self.shell.user_ns[args.out] = p.stdout
198 self.shell.user_ns[args.out] = p.stdout
193 else:
199 else:
194 to_close.append(p.stdout)
200 to_close.append(p.stdout)
195 if args.err:
201 if args.err:
196 self.shell.user_ns[args.err] = p.stderr
202 self.shell.user_ns[args.err] = p.stderr
197 else:
203 else:
198 to_close.append(p.stderr)
204 to_close.append(p.stderr)
199 self.job_manager.new(self._run_script, p, cell, to_close, daemon=True)
205 self.job_manager.new(self._run_script, p, cell, to_close, daemon=True)
200 if args.proc:
206 if args.proc:
201 self.shell.user_ns[args.proc] = p
207 self.shell.user_ns[args.proc] = p
202 return
208 return
203
209
204 try:
210 try:
205 out, err = p.communicate(cell)
211 out, err = p.communicate(cell)
206 except KeyboardInterrupt:
212 except KeyboardInterrupt:
207 try:
213 try:
208 p.send_signal(signal.SIGINT)
214 p.send_signal(signal.SIGINT)
209 time.sleep(0.1)
215 time.sleep(0.1)
210 if p.poll() is not None:
216 if p.poll() is not None:
211 print("Process is interrupted.")
217 print("Process is interrupted.")
212 return
218 return
213 p.terminate()
219 p.terminate()
214 time.sleep(0.1)
220 time.sleep(0.1)
215 if p.poll() is not None:
221 if p.poll() is not None:
216 print("Process is terminated.")
222 print("Process is terminated.")
217 return
223 return
218 p.kill()
224 p.kill()
219 print("Process is killed.")
225 print("Process is killed.")
220 except OSError:
226 except OSError:
221 pass
227 pass
222 except Exception as e:
228 except Exception as e:
223 print("Error while terminating subprocess (pid=%i): %s" \
229 print("Error while terminating subprocess (pid=%i): %s" \
224 % (p.pid, e))
230 % (p.pid, e))
225 return
231 return
226 out = py3compat.decode(out)
232 out = py3compat.decode(out)
227 err = py3compat.decode(err)
233 err = py3compat.decode(err)
228 if args.out:
234 if args.out:
229 self.shell.user_ns[args.out] = out
235 self.shell.user_ns[args.out] = out
230 else:
236 else:
231 sys.stdout.write(out)
237 sys.stdout.write(out)
232 sys.stdout.flush()
238 sys.stdout.flush()
233 if args.err:
239 if args.err:
234 self.shell.user_ns[args.err] = err
240 self.shell.user_ns[args.err] = err
235 else:
241 else:
236 sys.stderr.write(err)
242 sys.stderr.write(err)
237 sys.stderr.flush()
243 sys.stderr.flush()
244 if args.raise_error and p.returncode!=0:
245 raise CalledProcessError(p.returncode, cell, output=out, stderr=err)
238
246
239 def _run_script(self, p, cell, to_close):
247 def _run_script(self, p, cell, to_close):
240 """callback for running the script in the background"""
248 """callback for running the script in the background"""
241 p.stdin.write(cell)
249 p.stdin.write(cell)
242 p.stdin.close()
250 p.stdin.close()
243 for s in to_close:
251 for s in to_close:
244 s.close()
252 s.close()
245 p.wait()
253 p.wait()
246
254
247 @line_magic("killbgscripts")
255 @line_magic("killbgscripts")
248 def killbgscripts(self, _nouse_=''):
256 def killbgscripts(self, _nouse_=''):
249 """Kill all BG processes started by %%script and its family."""
257 """Kill all BG processes started by %%script and its family."""
250 self.kill_bg_processes()
258 self.kill_bg_processes()
251 print("All background processes were killed.")
259 print("All background processes were killed.")
252
260
253 def kill_bg_processes(self):
261 def kill_bg_processes(self):
254 """Kill all BG processes which are still running."""
262 """Kill all BG processes which are still running."""
255 if not self.bg_processes:
263 if not self.bg_processes:
256 return
264 return
257 for p in self.bg_processes:
265 for p in self.bg_processes:
258 if p.poll() is None:
266 if p.poll() is None:
259 try:
267 try:
260 p.send_signal(signal.SIGINT)
268 p.send_signal(signal.SIGINT)
261 except:
269 except:
262 pass
270 pass
263 time.sleep(0.1)
271 time.sleep(0.1)
264 self._gc_bg_processes()
272 self._gc_bg_processes()
265 if not self.bg_processes:
273 if not self.bg_processes:
266 return
274 return
267 for p in self.bg_processes:
275 for p in self.bg_processes:
268 if p.poll() is None:
276 if p.poll() is None:
269 try:
277 try:
270 p.terminate()
278 p.terminate()
271 except:
279 except:
272 pass
280 pass
273 time.sleep(0.1)
281 time.sleep(0.1)
274 self._gc_bg_processes()
282 self._gc_bg_processes()
275 if not self.bg_processes:
283 if not self.bg_processes:
276 return
284 return
277 for p in self.bg_processes:
285 for p in self.bg_processes:
278 if p.poll() is None:
286 if p.poll() is None:
279 try:
287 try:
280 p.kill()
288 p.kill()
281 except:
289 except:
282 pass
290 pass
283 self._gc_bg_processes()
291 self._gc_bg_processes()
284
292
285 def _gc_bg_processes(self):
293 def _gc_bg_processes(self):
286 self.bg_processes = [p for p in self.bg_processes if p.poll() is None]
294 self.bg_processes = [p for p in self.bg_processes if p.poll() is None]
@@ -1,709 +1,709 b''
1 # encoding: utf-8
1 # encoding: utf-8
2 """
2 """
3 Prefiltering components.
3 Prefiltering components.
4
4
5 Prefilters transform user input before it is exec'd by Python. These
5 Prefilters transform user input before it is exec'd by Python. These
6 transforms are used to implement additional syntax such as !ls and %magic.
6 transforms are used to implement additional syntax such as !ls and %magic.
7 """
7 """
8
8
9 # Copyright (c) IPython Development Team.
9 # Copyright (c) IPython Development Team.
10 # Distributed under the terms of the Modified BSD License.
10 # Distributed under the terms of the Modified BSD License.
11
11
12 from keyword import iskeyword
12 from keyword import iskeyword
13 import re
13 import re
14
14
15 from IPython.core.autocall import IPyAutocall
15 from IPython.core.autocall import IPyAutocall
16 from traitlets.config.configurable import Configurable
16 from traitlets.config.configurable import Configurable
17 from IPython.core.inputtransformer2 import (
17 from IPython.core.inputtransformer2 import (
18 ESC_MAGIC,
18 ESC_MAGIC,
19 ESC_QUOTE,
19 ESC_QUOTE,
20 ESC_QUOTE2,
20 ESC_QUOTE2,
21 ESC_PAREN,
21 ESC_PAREN,
22 )
22 )
23 from IPython.core.macro import Macro
23 from IPython.core.macro import Macro
24 from IPython.core.splitinput import LineInfo
24 from IPython.core.splitinput import LineInfo
25
25
26 from traitlets import (
26 from traitlets import (
27 List, Integer, Unicode, Bool, Instance, CRegExp
27 List, Integer, Unicode, Bool, Instance, CRegExp
28 )
28 )
29
29
30 #-----------------------------------------------------------------------------
30 #-----------------------------------------------------------------------------
31 # Global utilities, errors and constants
31 # Global utilities, errors and constants
32 #-----------------------------------------------------------------------------
32 #-----------------------------------------------------------------------------
33
33
34
34
35 class PrefilterError(Exception):
35 class PrefilterError(Exception):
36 pass
36 pass
37
37
38
38
39 # RegExp to identify potential function names
39 # RegExp to identify potential function names
40 re_fun_name = re.compile(r'[a-zA-Z_]([a-zA-Z0-9_.]*) *$')
40 re_fun_name = re.compile(r'[a-zA-Z_]([a-zA-Z0-9_.]*) *$')
41
41
42 # RegExp to exclude strings with this start from autocalling. In
42 # RegExp to exclude strings with this start from autocalling. In
43 # particular, all binary operators should be excluded, so that if foo is
43 # particular, all binary operators should be excluded, so that if foo is
44 # callable, foo OP bar doesn't become foo(OP bar), which is invalid. The
44 # callable, foo OP bar doesn't become foo(OP bar), which is invalid. The
45 # characters '!=()' don't need to be checked for, as the checkPythonChars
45 # characters '!=()' don't need to be checked for, as the checkPythonChars
46 # routine explicitly does so, to catch direct calls and rebindings of
46 # routine explicitly does so, to catch direct calls and rebindings of
47 # existing names.
47 # existing names.
48
48
49 # Warning: the '-' HAS TO BE AT THE END of the first group, otherwise
49 # Warning: the '-' HAS TO BE AT THE END of the first group, otherwise
50 # it affects the rest of the group in square brackets.
50 # it affects the rest of the group in square brackets.
51 re_exclude_auto = re.compile(r'^[,&^\|\*/\+-]'
51 re_exclude_auto = re.compile(r'^[,&^\|\*/\+-]'
52 r'|^is |^not |^in |^and |^or ')
52 r'|^is |^not |^in |^and |^or ')
53
53
54 # try to catch also methods for stuff in lists/tuples/dicts: off
54 # try to catch also methods for stuff in lists/tuples/dicts: off
55 # (experimental). For this to work, the line_split regexp would need
55 # (experimental). For this to work, the line_split regexp would need
56 # to be modified so it wouldn't break things at '['. That line is
56 # to be modified so it wouldn't break things at '['. That line is
57 # nasty enough that I shouldn't change it until I can test it _well_.
57 # nasty enough that I shouldn't change it until I can test it _well_.
58 #self.re_fun_name = re.compile (r'[a-zA-Z_]([a-zA-Z0-9_.\[\]]*) ?$')
58 #self.re_fun_name = re.compile (r'[a-zA-Z_]([a-zA-Z0-9_.\[\]]*) ?$')
59
59
60
60
61 # Handler Check Utilities
61 # Handler Check Utilities
62 def is_shadowed(identifier, ip):
62 def is_shadowed(identifier, ip):
63 """Is the given identifier defined in one of the namespaces which shadow
63 """Is the given identifier defined in one of the namespaces which shadow
64 the alias and magic namespaces? Note that an identifier is different
64 the alias and magic namespaces? Note that an identifier is different
65 than ifun, because it can not contain a '.' character."""
65 than ifun, because it can not contain a '.' character."""
66 # This is much safer than calling ofind, which can change state
66 # This is much safer than calling ofind, which can change state
67 return (identifier in ip.user_ns \
67 return (identifier in ip.user_ns \
68 or identifier in ip.user_global_ns \
68 or identifier in ip.user_global_ns \
69 or identifier in ip.ns_table['builtin']\
69 or identifier in ip.ns_table['builtin']\
70 or iskeyword(identifier))
70 or iskeyword(identifier))
71
71
72
72
73 #-----------------------------------------------------------------------------
73 #-----------------------------------------------------------------------------
74 # Main Prefilter manager
74 # Main Prefilter manager
75 #-----------------------------------------------------------------------------
75 #-----------------------------------------------------------------------------
76
76
77
77
78 class PrefilterManager(Configurable):
78 class PrefilterManager(Configurable):
79 """Main prefilter component.
79 """Main prefilter component.
80
80
81 The IPython prefilter is run on all user input before it is run. The
81 The IPython prefilter is run on all user input before it is run. The
82 prefilter consumes lines of input and produces transformed lines of
82 prefilter consumes lines of input and produces transformed lines of
83 input.
83 input.
84
84
85 The iplementation consists of two phases:
85 The implementation consists of two phases:
86
86
87 1. Transformers
87 1. Transformers
88 2. Checkers and handlers
88 2. Checkers and handlers
89
89
90 Over time, we plan on deprecating the checkers and handlers and doing
90 Over time, we plan on deprecating the checkers and handlers and doing
91 everything in the transformers.
91 everything in the transformers.
92
92
93 The transformers are instances of :class:`PrefilterTransformer` and have
93 The transformers are instances of :class:`PrefilterTransformer` and have
94 a single method :meth:`transform` that takes a line and returns a
94 a single method :meth:`transform` that takes a line and returns a
95 transformed line. The transformation can be accomplished using any
95 transformed line. The transformation can be accomplished using any
96 tool, but our current ones use regular expressions for speed.
96 tool, but our current ones use regular expressions for speed.
97
97
98 After all the transformers have been run, the line is fed to the checkers,
98 After all the transformers have been run, the line is fed to the checkers,
99 which are instances of :class:`PrefilterChecker`. The line is passed to
99 which are instances of :class:`PrefilterChecker`. The line is passed to
100 the :meth:`check` method, which either returns `None` or a
100 the :meth:`check` method, which either returns `None` or a
101 :class:`PrefilterHandler` instance. If `None` is returned, the other
101 :class:`PrefilterHandler` instance. If `None` is returned, the other
102 checkers are tried. If an :class:`PrefilterHandler` instance is returned,
102 checkers are tried. If an :class:`PrefilterHandler` instance is returned,
103 the line is passed to the :meth:`handle` method of the returned
103 the line is passed to the :meth:`handle` method of the returned
104 handler and no further checkers are tried.
104 handler and no further checkers are tried.
105
105
106 Both transformers and checkers have a `priority` attribute, that determines
106 Both transformers and checkers have a `priority` attribute, that determines
107 the order in which they are called. Smaller priorities are tried first.
107 the order in which they are called. Smaller priorities are tried first.
108
108
109 Both transformers and checkers also have `enabled` attribute, which is
109 Both transformers and checkers also have `enabled` attribute, which is
110 a boolean that determines if the instance is used.
110 a boolean that determines if the instance is used.
111
111
112 Users or developers can change the priority or enabled attribute of
112 Users or developers can change the priority or enabled attribute of
113 transformers or checkers, but they must call the :meth:`sort_checkers`
113 transformers or checkers, but they must call the :meth:`sort_checkers`
114 or :meth:`sort_transformers` method after changing the priority.
114 or :meth:`sort_transformers` method after changing the priority.
115 """
115 """
116
116
117 multi_line_specials = Bool(True).tag(config=True)
117 multi_line_specials = Bool(True).tag(config=True)
118 shell = Instance('IPython.core.interactiveshell.InteractiveShellABC', allow_none=True)
118 shell = Instance('IPython.core.interactiveshell.InteractiveShellABC', allow_none=True)
119
119
120 def __init__(self, shell=None, **kwargs):
120 def __init__(self, shell=None, **kwargs):
121 super(PrefilterManager, self).__init__(shell=shell, **kwargs)
121 super(PrefilterManager, self).__init__(shell=shell, **kwargs)
122 self.shell = shell
122 self.shell = shell
123 self.init_transformers()
123 self.init_transformers()
124 self.init_handlers()
124 self.init_handlers()
125 self.init_checkers()
125 self.init_checkers()
126
126
127 #-------------------------------------------------------------------------
127 #-------------------------------------------------------------------------
128 # API for managing transformers
128 # API for managing transformers
129 #-------------------------------------------------------------------------
129 #-------------------------------------------------------------------------
130
130
131 def init_transformers(self):
131 def init_transformers(self):
132 """Create the default transformers."""
132 """Create the default transformers."""
133 self._transformers = []
133 self._transformers = []
134 for transformer_cls in _default_transformers:
134 for transformer_cls in _default_transformers:
135 transformer_cls(
135 transformer_cls(
136 shell=self.shell, prefilter_manager=self, parent=self
136 shell=self.shell, prefilter_manager=self, parent=self
137 )
137 )
138
138
139 def sort_transformers(self):
139 def sort_transformers(self):
140 """Sort the transformers by priority.
140 """Sort the transformers by priority.
141
141
142 This must be called after the priority of a transformer is changed.
142 This must be called after the priority of a transformer is changed.
143 The :meth:`register_transformer` method calls this automatically.
143 The :meth:`register_transformer` method calls this automatically.
144 """
144 """
145 self._transformers.sort(key=lambda x: x.priority)
145 self._transformers.sort(key=lambda x: x.priority)
146
146
147 @property
147 @property
148 def transformers(self):
148 def transformers(self):
149 """Return a list of checkers, sorted by priority."""
149 """Return a list of checkers, sorted by priority."""
150 return self._transformers
150 return self._transformers
151
151
152 def register_transformer(self, transformer):
152 def register_transformer(self, transformer):
153 """Register a transformer instance."""
153 """Register a transformer instance."""
154 if transformer not in self._transformers:
154 if transformer not in self._transformers:
155 self._transformers.append(transformer)
155 self._transformers.append(transformer)
156 self.sort_transformers()
156 self.sort_transformers()
157
157
158 def unregister_transformer(self, transformer):
158 def unregister_transformer(self, transformer):
159 """Unregister a transformer instance."""
159 """Unregister a transformer instance."""
160 if transformer in self._transformers:
160 if transformer in self._transformers:
161 self._transformers.remove(transformer)
161 self._transformers.remove(transformer)
162
162
163 #-------------------------------------------------------------------------
163 #-------------------------------------------------------------------------
164 # API for managing checkers
164 # API for managing checkers
165 #-------------------------------------------------------------------------
165 #-------------------------------------------------------------------------
166
166
167 def init_checkers(self):
167 def init_checkers(self):
168 """Create the default checkers."""
168 """Create the default checkers."""
169 self._checkers = []
169 self._checkers = []
170 for checker in _default_checkers:
170 for checker in _default_checkers:
171 checker(
171 checker(
172 shell=self.shell, prefilter_manager=self, parent=self
172 shell=self.shell, prefilter_manager=self, parent=self
173 )
173 )
174
174
175 def sort_checkers(self):
175 def sort_checkers(self):
176 """Sort the checkers by priority.
176 """Sort the checkers by priority.
177
177
178 This must be called after the priority of a checker is changed.
178 This must be called after the priority of a checker is changed.
179 The :meth:`register_checker` method calls this automatically.
179 The :meth:`register_checker` method calls this automatically.
180 """
180 """
181 self._checkers.sort(key=lambda x: x.priority)
181 self._checkers.sort(key=lambda x: x.priority)
182
182
183 @property
183 @property
184 def checkers(self):
184 def checkers(self):
185 """Return a list of checkers, sorted by priority."""
185 """Return a list of checkers, sorted by priority."""
186 return self._checkers
186 return self._checkers
187
187
188 def register_checker(self, checker):
188 def register_checker(self, checker):
189 """Register a checker instance."""
189 """Register a checker instance."""
190 if checker not in self._checkers:
190 if checker not in self._checkers:
191 self._checkers.append(checker)
191 self._checkers.append(checker)
192 self.sort_checkers()
192 self.sort_checkers()
193
193
194 def unregister_checker(self, checker):
194 def unregister_checker(self, checker):
195 """Unregister a checker instance."""
195 """Unregister a checker instance."""
196 if checker in self._checkers:
196 if checker in self._checkers:
197 self._checkers.remove(checker)
197 self._checkers.remove(checker)
198
198
199 #-------------------------------------------------------------------------
199 #-------------------------------------------------------------------------
200 # API for managing handlers
200 # API for managing handlers
201 #-------------------------------------------------------------------------
201 #-------------------------------------------------------------------------
202
202
203 def init_handlers(self):
203 def init_handlers(self):
204 """Create the default handlers."""
204 """Create the default handlers."""
205 self._handlers = {}
205 self._handlers = {}
206 self._esc_handlers = {}
206 self._esc_handlers = {}
207 for handler in _default_handlers:
207 for handler in _default_handlers:
208 handler(
208 handler(
209 shell=self.shell, prefilter_manager=self, parent=self
209 shell=self.shell, prefilter_manager=self, parent=self
210 )
210 )
211
211
212 @property
212 @property
213 def handlers(self):
213 def handlers(self):
214 """Return a dict of all the handlers."""
214 """Return a dict of all the handlers."""
215 return self._handlers
215 return self._handlers
216
216
217 def register_handler(self, name, handler, esc_strings):
217 def register_handler(self, name, handler, esc_strings):
218 """Register a handler instance by name with esc_strings."""
218 """Register a handler instance by name with esc_strings."""
219 self._handlers[name] = handler
219 self._handlers[name] = handler
220 for esc_str in esc_strings:
220 for esc_str in esc_strings:
221 self._esc_handlers[esc_str] = handler
221 self._esc_handlers[esc_str] = handler
222
222
223 def unregister_handler(self, name, handler, esc_strings):
223 def unregister_handler(self, name, handler, esc_strings):
224 """Unregister a handler instance by name with esc_strings."""
224 """Unregister a handler instance by name with esc_strings."""
225 try:
225 try:
226 del self._handlers[name]
226 del self._handlers[name]
227 except KeyError:
227 except KeyError:
228 pass
228 pass
229 for esc_str in esc_strings:
229 for esc_str in esc_strings:
230 h = self._esc_handlers.get(esc_str)
230 h = self._esc_handlers.get(esc_str)
231 if h is handler:
231 if h is handler:
232 del self._esc_handlers[esc_str]
232 del self._esc_handlers[esc_str]
233
233
234 def get_handler_by_name(self, name):
234 def get_handler_by_name(self, name):
235 """Get a handler by its name."""
235 """Get a handler by its name."""
236 return self._handlers.get(name)
236 return self._handlers.get(name)
237
237
238 def get_handler_by_esc(self, esc_str):
238 def get_handler_by_esc(self, esc_str):
239 """Get a handler by its escape string."""
239 """Get a handler by its escape string."""
240 return self._esc_handlers.get(esc_str)
240 return self._esc_handlers.get(esc_str)
241
241
242 #-------------------------------------------------------------------------
242 #-------------------------------------------------------------------------
243 # Main prefiltering API
243 # Main prefiltering API
244 #-------------------------------------------------------------------------
244 #-------------------------------------------------------------------------
245
245
246 def prefilter_line_info(self, line_info):
246 def prefilter_line_info(self, line_info):
247 """Prefilter a line that has been converted to a LineInfo object.
247 """Prefilter a line that has been converted to a LineInfo object.
248
248
249 This implements the checker/handler part of the prefilter pipe.
249 This implements the checker/handler part of the prefilter pipe.
250 """
250 """
251 # print "prefilter_line_info: ", line_info
251 # print "prefilter_line_info: ", line_info
252 handler = self.find_handler(line_info)
252 handler = self.find_handler(line_info)
253 return handler.handle(line_info)
253 return handler.handle(line_info)
254
254
255 def find_handler(self, line_info):
255 def find_handler(self, line_info):
256 """Find a handler for the line_info by trying checkers."""
256 """Find a handler for the line_info by trying checkers."""
257 for checker in self.checkers:
257 for checker in self.checkers:
258 if checker.enabled:
258 if checker.enabled:
259 handler = checker.check(line_info)
259 handler = checker.check(line_info)
260 if handler:
260 if handler:
261 return handler
261 return handler
262 return self.get_handler_by_name('normal')
262 return self.get_handler_by_name('normal')
263
263
264 def transform_line(self, line, continue_prompt):
264 def transform_line(self, line, continue_prompt):
265 """Calls the enabled transformers in order of increasing priority."""
265 """Calls the enabled transformers in order of increasing priority."""
266 for transformer in self.transformers:
266 for transformer in self.transformers:
267 if transformer.enabled:
267 if transformer.enabled:
268 line = transformer.transform(line, continue_prompt)
268 line = transformer.transform(line, continue_prompt)
269 return line
269 return line
270
270
271 def prefilter_line(self, line, continue_prompt=False):
271 def prefilter_line(self, line, continue_prompt=False):
272 """Prefilter a single input line as text.
272 """Prefilter a single input line as text.
273
273
274 This method prefilters a single line of text by calling the
274 This method prefilters a single line of text by calling the
275 transformers and then the checkers/handlers.
275 transformers and then the checkers/handlers.
276 """
276 """
277
277
278 # print "prefilter_line: ", line, continue_prompt
278 # print "prefilter_line: ", line, continue_prompt
279 # All handlers *must* return a value, even if it's blank ('').
279 # All handlers *must* return a value, even if it's blank ('').
280
280
281 # save the line away in case we crash, so the post-mortem handler can
281 # save the line away in case we crash, so the post-mortem handler can
282 # record it
282 # record it
283 self.shell._last_input_line = line
283 self.shell._last_input_line = line
284
284
285 if not line:
285 if not line:
286 # Return immediately on purely empty lines, so that if the user
286 # Return immediately on purely empty lines, so that if the user
287 # previously typed some whitespace that started a continuation
287 # previously typed some whitespace that started a continuation
288 # prompt, he can break out of that loop with just an empty line.
288 # prompt, he can break out of that loop with just an empty line.
289 # This is how the default python prompt works.
289 # This is how the default python prompt works.
290 return ''
290 return ''
291
291
292 # At this point, we invoke our transformers.
292 # At this point, we invoke our transformers.
293 if not continue_prompt or (continue_prompt and self.multi_line_specials):
293 if not continue_prompt or (continue_prompt and self.multi_line_specials):
294 line = self.transform_line(line, continue_prompt)
294 line = self.transform_line(line, continue_prompt)
295
295
296 # Now we compute line_info for the checkers and handlers
296 # Now we compute line_info for the checkers and handlers
297 line_info = LineInfo(line, continue_prompt)
297 line_info = LineInfo(line, continue_prompt)
298
298
299 # the input history needs to track even empty lines
299 # the input history needs to track even empty lines
300 stripped = line.strip()
300 stripped = line.strip()
301
301
302 normal_handler = self.get_handler_by_name('normal')
302 normal_handler = self.get_handler_by_name('normal')
303 if not stripped:
303 if not stripped:
304 return normal_handler.handle(line_info)
304 return normal_handler.handle(line_info)
305
305
306 # special handlers are only allowed for single line statements
306 # special handlers are only allowed for single line statements
307 if continue_prompt and not self.multi_line_specials:
307 if continue_prompt and not self.multi_line_specials:
308 return normal_handler.handle(line_info)
308 return normal_handler.handle(line_info)
309
309
310 prefiltered = self.prefilter_line_info(line_info)
310 prefiltered = self.prefilter_line_info(line_info)
311 # print "prefiltered line: %r" % prefiltered
311 # print "prefiltered line: %r" % prefiltered
312 return prefiltered
312 return prefiltered
313
313
314 def prefilter_lines(self, lines, continue_prompt=False):
314 def prefilter_lines(self, lines, continue_prompt=False):
315 """Prefilter multiple input lines of text.
315 """Prefilter multiple input lines of text.
316
316
317 This is the main entry point for prefiltering multiple lines of
317 This is the main entry point for prefiltering multiple lines of
318 input. This simply calls :meth:`prefilter_line` for each line of
318 input. This simply calls :meth:`prefilter_line` for each line of
319 input.
319 input.
320
320
321 This covers cases where there are multiple lines in the user entry,
321 This covers cases where there are multiple lines in the user entry,
322 which is the case when the user goes back to a multiline history
322 which is the case when the user goes back to a multiline history
323 entry and presses enter.
323 entry and presses enter.
324 """
324 """
325 llines = lines.rstrip('\n').split('\n')
325 llines = lines.rstrip('\n').split('\n')
326 # We can get multiple lines in one shot, where multiline input 'blends'
326 # We can get multiple lines in one shot, where multiline input 'blends'
327 # into one line, in cases like recalling from the readline history
327 # into one line, in cases like recalling from the readline history
328 # buffer. We need to make sure that in such cases, we correctly
328 # buffer. We need to make sure that in such cases, we correctly
329 # communicate downstream which line is first and which are continuation
329 # communicate downstream which line is first and which are continuation
330 # ones.
330 # ones.
331 if len(llines) > 1:
331 if len(llines) > 1:
332 out = '\n'.join([self.prefilter_line(line, lnum>0)
332 out = '\n'.join([self.prefilter_line(line, lnum>0)
333 for lnum, line in enumerate(llines) ])
333 for lnum, line in enumerate(llines) ])
334 else:
334 else:
335 out = self.prefilter_line(llines[0], continue_prompt)
335 out = self.prefilter_line(llines[0], continue_prompt)
336
336
337 return out
337 return out
338
338
339 #-----------------------------------------------------------------------------
339 #-----------------------------------------------------------------------------
340 # Prefilter transformers
340 # Prefilter transformers
341 #-----------------------------------------------------------------------------
341 #-----------------------------------------------------------------------------
342
342
343
343
344 class PrefilterTransformer(Configurable):
344 class PrefilterTransformer(Configurable):
345 """Transform a line of user input."""
345 """Transform a line of user input."""
346
346
347 priority = Integer(100).tag(config=True)
347 priority = Integer(100).tag(config=True)
348 # Transformers don't currently use shell or prefilter_manager, but as we
348 # Transformers don't currently use shell or prefilter_manager, but as we
349 # move away from checkers and handlers, they will need them.
349 # move away from checkers and handlers, they will need them.
350 shell = Instance('IPython.core.interactiveshell.InteractiveShellABC', allow_none=True)
350 shell = Instance('IPython.core.interactiveshell.InteractiveShellABC', allow_none=True)
351 prefilter_manager = Instance('IPython.core.prefilter.PrefilterManager', allow_none=True)
351 prefilter_manager = Instance('IPython.core.prefilter.PrefilterManager', allow_none=True)
352 enabled = Bool(True).tag(config=True)
352 enabled = Bool(True).tag(config=True)
353
353
354 def __init__(self, shell=None, prefilter_manager=None, **kwargs):
354 def __init__(self, shell=None, prefilter_manager=None, **kwargs):
355 super(PrefilterTransformer, self).__init__(
355 super(PrefilterTransformer, self).__init__(
356 shell=shell, prefilter_manager=prefilter_manager, **kwargs
356 shell=shell, prefilter_manager=prefilter_manager, **kwargs
357 )
357 )
358 self.prefilter_manager.register_transformer(self)
358 self.prefilter_manager.register_transformer(self)
359
359
360 def transform(self, line, continue_prompt):
360 def transform(self, line, continue_prompt):
361 """Transform a line, returning the new one."""
361 """Transform a line, returning the new one."""
362 return None
362 return None
363
363
364 def __repr__(self):
364 def __repr__(self):
365 return "<%s(priority=%r, enabled=%r)>" % (
365 return "<%s(priority=%r, enabled=%r)>" % (
366 self.__class__.__name__, self.priority, self.enabled)
366 self.__class__.__name__, self.priority, self.enabled)
367
367
368
368
369 #-----------------------------------------------------------------------------
369 #-----------------------------------------------------------------------------
370 # Prefilter checkers
370 # Prefilter checkers
371 #-----------------------------------------------------------------------------
371 #-----------------------------------------------------------------------------
372
372
373
373
374 class PrefilterChecker(Configurable):
374 class PrefilterChecker(Configurable):
375 """Inspect an input line and return a handler for that line."""
375 """Inspect an input line and return a handler for that line."""
376
376
377 priority = Integer(100).tag(config=True)
377 priority = Integer(100).tag(config=True)
378 shell = Instance('IPython.core.interactiveshell.InteractiveShellABC', allow_none=True)
378 shell = Instance('IPython.core.interactiveshell.InteractiveShellABC', allow_none=True)
379 prefilter_manager = Instance('IPython.core.prefilter.PrefilterManager', allow_none=True)
379 prefilter_manager = Instance('IPython.core.prefilter.PrefilterManager', allow_none=True)
380 enabled = Bool(True).tag(config=True)
380 enabled = Bool(True).tag(config=True)
381
381
382 def __init__(self, shell=None, prefilter_manager=None, **kwargs):
382 def __init__(self, shell=None, prefilter_manager=None, **kwargs):
383 super(PrefilterChecker, self).__init__(
383 super(PrefilterChecker, self).__init__(
384 shell=shell, prefilter_manager=prefilter_manager, **kwargs
384 shell=shell, prefilter_manager=prefilter_manager, **kwargs
385 )
385 )
386 self.prefilter_manager.register_checker(self)
386 self.prefilter_manager.register_checker(self)
387
387
388 def check(self, line_info):
388 def check(self, line_info):
389 """Inspect line_info and return a handler instance or None."""
389 """Inspect line_info and return a handler instance or None."""
390 return None
390 return None
391
391
392 def __repr__(self):
392 def __repr__(self):
393 return "<%s(priority=%r, enabled=%r)>" % (
393 return "<%s(priority=%r, enabled=%r)>" % (
394 self.__class__.__name__, self.priority, self.enabled)
394 self.__class__.__name__, self.priority, self.enabled)
395
395
396
396
397 class EmacsChecker(PrefilterChecker):
397 class EmacsChecker(PrefilterChecker):
398
398
399 priority = Integer(100).tag(config=True)
399 priority = Integer(100).tag(config=True)
400 enabled = Bool(False).tag(config=True)
400 enabled = Bool(False).tag(config=True)
401
401
402 def check(self, line_info):
402 def check(self, line_info):
403 "Emacs ipython-mode tags certain input lines."
403 "Emacs ipython-mode tags certain input lines."
404 if line_info.line.endswith('# PYTHON-MODE'):
404 if line_info.line.endswith('# PYTHON-MODE'):
405 return self.prefilter_manager.get_handler_by_name('emacs')
405 return self.prefilter_manager.get_handler_by_name('emacs')
406 else:
406 else:
407 return None
407 return None
408
408
409
409
410 class MacroChecker(PrefilterChecker):
410 class MacroChecker(PrefilterChecker):
411
411
412 priority = Integer(250).tag(config=True)
412 priority = Integer(250).tag(config=True)
413
413
414 def check(self, line_info):
414 def check(self, line_info):
415 obj = self.shell.user_ns.get(line_info.ifun)
415 obj = self.shell.user_ns.get(line_info.ifun)
416 if isinstance(obj, Macro):
416 if isinstance(obj, Macro):
417 return self.prefilter_manager.get_handler_by_name('macro')
417 return self.prefilter_manager.get_handler_by_name('macro')
418 else:
418 else:
419 return None
419 return None
420
420
421
421
422 class IPyAutocallChecker(PrefilterChecker):
422 class IPyAutocallChecker(PrefilterChecker):
423
423
424 priority = Integer(300).tag(config=True)
424 priority = Integer(300).tag(config=True)
425
425
426 def check(self, line_info):
426 def check(self, line_info):
427 "Instances of IPyAutocall in user_ns get autocalled immediately"
427 "Instances of IPyAutocall in user_ns get autocalled immediately"
428 obj = self.shell.user_ns.get(line_info.ifun, None)
428 obj = self.shell.user_ns.get(line_info.ifun, None)
429 if isinstance(obj, IPyAutocall):
429 if isinstance(obj, IPyAutocall):
430 obj.set_ip(self.shell)
430 obj.set_ip(self.shell)
431 return self.prefilter_manager.get_handler_by_name('auto')
431 return self.prefilter_manager.get_handler_by_name('auto')
432 else:
432 else:
433 return None
433 return None
434
434
435
435
436 class AssignmentChecker(PrefilterChecker):
436 class AssignmentChecker(PrefilterChecker):
437
437
438 priority = Integer(600).tag(config=True)
438 priority = Integer(600).tag(config=True)
439
439
440 def check(self, line_info):
440 def check(self, line_info):
441 """Check to see if user is assigning to a var for the first time, in
441 """Check to see if user is assigning to a var for the first time, in
442 which case we want to avoid any sort of automagic / autocall games.
442 which case we want to avoid any sort of automagic / autocall games.
443
443
444 This allows users to assign to either alias or magic names true python
444 This allows users to assign to either alias or magic names true python
445 variables (the magic/alias systems always take second seat to true
445 variables (the magic/alias systems always take second seat to true
446 python code). E.g. ls='hi', or ls,that=1,2"""
446 python code). E.g. ls='hi', or ls,that=1,2"""
447 if line_info.the_rest:
447 if line_info.the_rest:
448 if line_info.the_rest[0] in '=,':
448 if line_info.the_rest[0] in '=,':
449 return self.prefilter_manager.get_handler_by_name('normal')
449 return self.prefilter_manager.get_handler_by_name('normal')
450 else:
450 else:
451 return None
451 return None
452
452
453
453
454 class AutoMagicChecker(PrefilterChecker):
454 class AutoMagicChecker(PrefilterChecker):
455
455
456 priority = Integer(700).tag(config=True)
456 priority = Integer(700).tag(config=True)
457
457
458 def check(self, line_info):
458 def check(self, line_info):
459 """If the ifun is magic, and automagic is on, run it. Note: normal,
459 """If the ifun is magic, and automagic is on, run it. Note: normal,
460 non-auto magic would already have been triggered via '%' in
460 non-auto magic would already have been triggered via '%' in
461 check_esc_chars. This just checks for automagic. Also, before
461 check_esc_chars. This just checks for automagic. Also, before
462 triggering the magic handler, make sure that there is nothing in the
462 triggering the magic handler, make sure that there is nothing in the
463 user namespace which could shadow it."""
463 user namespace which could shadow it."""
464 if not self.shell.automagic or not self.shell.find_magic(line_info.ifun):
464 if not self.shell.automagic or not self.shell.find_magic(line_info.ifun):
465 return None
465 return None
466
466
467 # We have a likely magic method. Make sure we should actually call it.
467 # We have a likely magic method. Make sure we should actually call it.
468 if line_info.continue_prompt and not self.prefilter_manager.multi_line_specials:
468 if line_info.continue_prompt and not self.prefilter_manager.multi_line_specials:
469 return None
469 return None
470
470
471 head = line_info.ifun.split('.',1)[0]
471 head = line_info.ifun.split('.',1)[0]
472 if is_shadowed(head, self.shell):
472 if is_shadowed(head, self.shell):
473 return None
473 return None
474
474
475 return self.prefilter_manager.get_handler_by_name('magic')
475 return self.prefilter_manager.get_handler_by_name('magic')
476
476
477
477
478 class PythonOpsChecker(PrefilterChecker):
478 class PythonOpsChecker(PrefilterChecker):
479
479
480 priority = Integer(900).tag(config=True)
480 priority = Integer(900).tag(config=True)
481
481
482 def check(self, line_info):
482 def check(self, line_info):
483 """If the 'rest' of the line begins with a function call or pretty much
483 """If the 'rest' of the line begins with a function call or pretty much
484 any python operator, we should simply execute the line (regardless of
484 any python operator, we should simply execute the line (regardless of
485 whether or not there's a possible autocall expansion). This avoids
485 whether or not there's a possible autocall expansion). This avoids
486 spurious (and very confusing) geattr() accesses."""
486 spurious (and very confusing) geattr() accesses."""
487 if line_info.the_rest and line_info.the_rest[0] in '!=()<>,+*/%^&|':
487 if line_info.the_rest and line_info.the_rest[0] in '!=()<>,+*/%^&|':
488 return self.prefilter_manager.get_handler_by_name('normal')
488 return self.prefilter_manager.get_handler_by_name('normal')
489 else:
489 else:
490 return None
490 return None
491
491
492
492
493 class AutocallChecker(PrefilterChecker):
493 class AutocallChecker(PrefilterChecker):
494
494
495 priority = Integer(1000).tag(config=True)
495 priority = Integer(1000).tag(config=True)
496
496
497 function_name_regexp = CRegExp(re_fun_name,
497 function_name_regexp = CRegExp(re_fun_name,
498 help="RegExp to identify potential function names."
498 help="RegExp to identify potential function names."
499 ).tag(config=True)
499 ).tag(config=True)
500 exclude_regexp = CRegExp(re_exclude_auto,
500 exclude_regexp = CRegExp(re_exclude_auto,
501 help="RegExp to exclude strings with this start from autocalling."
501 help="RegExp to exclude strings with this start from autocalling."
502 ).tag(config=True)
502 ).tag(config=True)
503
503
504 def check(self, line_info):
504 def check(self, line_info):
505 "Check if the initial word/function is callable and autocall is on."
505 "Check if the initial word/function is callable and autocall is on."
506 if not self.shell.autocall:
506 if not self.shell.autocall:
507 return None
507 return None
508
508
509 oinfo = line_info.ofind(self.shell) # This can mutate state via getattr
509 oinfo = line_info.ofind(self.shell) # This can mutate state via getattr
510 if not oinfo['found']:
510 if not oinfo['found']:
511 return None
511 return None
512
512
513 ignored_funs = ['b', 'f', 'r', 'u', 'br', 'rb', 'fr', 'rf']
513 ignored_funs = ['b', 'f', 'r', 'u', 'br', 'rb', 'fr', 'rf']
514 ifun = line_info.ifun
514 ifun = line_info.ifun
515 line = line_info.line
515 line = line_info.line
516 if ifun.lower() in ignored_funs and (line.startswith(ifun + "'") or line.startswith(ifun + '"')):
516 if ifun.lower() in ignored_funs and (line.startswith(ifun + "'") or line.startswith(ifun + '"')):
517 return None
517 return None
518
518
519 if callable(oinfo['obj']) \
519 if callable(oinfo['obj']) \
520 and (not self.exclude_regexp.match(line_info.the_rest)) \
520 and (not self.exclude_regexp.match(line_info.the_rest)) \
521 and self.function_name_regexp.match(line_info.ifun):
521 and self.function_name_regexp.match(line_info.ifun):
522 return self.prefilter_manager.get_handler_by_name('auto')
522 return self.prefilter_manager.get_handler_by_name('auto')
523 else:
523 else:
524 return None
524 return None
525
525
526
526
527 #-----------------------------------------------------------------------------
527 #-----------------------------------------------------------------------------
528 # Prefilter handlers
528 # Prefilter handlers
529 #-----------------------------------------------------------------------------
529 #-----------------------------------------------------------------------------
530
530
531
531
532 class PrefilterHandler(Configurable):
532 class PrefilterHandler(Configurable):
533
533
534 handler_name = Unicode('normal')
534 handler_name = Unicode('normal')
535 esc_strings = List([])
535 esc_strings = List([])
536 shell = Instance('IPython.core.interactiveshell.InteractiveShellABC', allow_none=True)
536 shell = Instance('IPython.core.interactiveshell.InteractiveShellABC', allow_none=True)
537 prefilter_manager = Instance('IPython.core.prefilter.PrefilterManager', allow_none=True)
537 prefilter_manager = Instance('IPython.core.prefilter.PrefilterManager', allow_none=True)
538
538
539 def __init__(self, shell=None, prefilter_manager=None, **kwargs):
539 def __init__(self, shell=None, prefilter_manager=None, **kwargs):
540 super(PrefilterHandler, self).__init__(
540 super(PrefilterHandler, self).__init__(
541 shell=shell, prefilter_manager=prefilter_manager, **kwargs
541 shell=shell, prefilter_manager=prefilter_manager, **kwargs
542 )
542 )
543 self.prefilter_manager.register_handler(
543 self.prefilter_manager.register_handler(
544 self.handler_name,
544 self.handler_name,
545 self,
545 self,
546 self.esc_strings
546 self.esc_strings
547 )
547 )
548
548
549 def handle(self, line_info):
549 def handle(self, line_info):
550 # print "normal: ", line_info
550 # print "normal: ", line_info
551 """Handle normal input lines. Use as a template for handlers."""
551 """Handle normal input lines. Use as a template for handlers."""
552
552
553 # With autoindent on, we need some way to exit the input loop, and I
553 # With autoindent on, we need some way to exit the input loop, and I
554 # don't want to force the user to have to backspace all the way to
554 # don't want to force the user to have to backspace all the way to
555 # clear the line. The rule will be in this case, that either two
555 # clear the line. The rule will be in this case, that either two
556 # lines of pure whitespace in a row, or a line of pure whitespace but
556 # lines of pure whitespace in a row, or a line of pure whitespace but
557 # of a size different to the indent level, will exit the input loop.
557 # of a size different to the indent level, will exit the input loop.
558 line = line_info.line
558 line = line_info.line
559 continue_prompt = line_info.continue_prompt
559 continue_prompt = line_info.continue_prompt
560
560
561 if (continue_prompt and
561 if (continue_prompt and
562 self.shell.autoindent and
562 self.shell.autoindent and
563 line.isspace() and
563 line.isspace() and
564 0 < abs(len(line) - self.shell.indent_current_nsp) <= 2):
564 0 < abs(len(line) - self.shell.indent_current_nsp) <= 2):
565 line = ''
565 line = ''
566
566
567 return line
567 return line
568
568
569 def __str__(self):
569 def __str__(self):
570 return "<%s(name=%s)>" % (self.__class__.__name__, self.handler_name)
570 return "<%s(name=%s)>" % (self.__class__.__name__, self.handler_name)
571
571
572
572
573 class MacroHandler(PrefilterHandler):
573 class MacroHandler(PrefilterHandler):
574 handler_name = Unicode("macro")
574 handler_name = Unicode("macro")
575
575
576 def handle(self, line_info):
576 def handle(self, line_info):
577 obj = self.shell.user_ns.get(line_info.ifun)
577 obj = self.shell.user_ns.get(line_info.ifun)
578 pre_space = line_info.pre_whitespace
578 pre_space = line_info.pre_whitespace
579 line_sep = "\n" + pre_space
579 line_sep = "\n" + pre_space
580 return pre_space + line_sep.join(obj.value.splitlines())
580 return pre_space + line_sep.join(obj.value.splitlines())
581
581
582
582
583 class MagicHandler(PrefilterHandler):
583 class MagicHandler(PrefilterHandler):
584
584
585 handler_name = Unicode('magic')
585 handler_name = Unicode('magic')
586 esc_strings = List([ESC_MAGIC])
586 esc_strings = List([ESC_MAGIC])
587
587
588 def handle(self, line_info):
588 def handle(self, line_info):
589 """Execute magic functions."""
589 """Execute magic functions."""
590 ifun = line_info.ifun
590 ifun = line_info.ifun
591 the_rest = line_info.the_rest
591 the_rest = line_info.the_rest
592 #Prepare arguments for get_ipython().run_line_magic(magic_name, magic_args)
592 #Prepare arguments for get_ipython().run_line_magic(magic_name, magic_args)
593 t_arg_s = ifun + " " + the_rest
593 t_arg_s = ifun + " " + the_rest
594 t_magic_name, _, t_magic_arg_s = t_arg_s.partition(' ')
594 t_magic_name, _, t_magic_arg_s = t_arg_s.partition(' ')
595 t_magic_name = t_magic_name.lstrip(ESC_MAGIC)
595 t_magic_name = t_magic_name.lstrip(ESC_MAGIC)
596 cmd = '%sget_ipython().run_line_magic(%r, %r)' % (line_info.pre_whitespace, t_magic_name, t_magic_arg_s)
596 cmd = '%sget_ipython().run_line_magic(%r, %r)' % (line_info.pre_whitespace, t_magic_name, t_magic_arg_s)
597 return cmd
597 return cmd
598
598
599
599
600 class AutoHandler(PrefilterHandler):
600 class AutoHandler(PrefilterHandler):
601
601
602 handler_name = Unicode('auto')
602 handler_name = Unicode('auto')
603 esc_strings = List([ESC_PAREN, ESC_QUOTE, ESC_QUOTE2])
603 esc_strings = List([ESC_PAREN, ESC_QUOTE, ESC_QUOTE2])
604
604
605 def handle(self, line_info):
605 def handle(self, line_info):
606 """Handle lines which can be auto-executed, quoting if requested."""
606 """Handle lines which can be auto-executed, quoting if requested."""
607 line = line_info.line
607 line = line_info.line
608 ifun = line_info.ifun
608 ifun = line_info.ifun
609 the_rest = line_info.the_rest
609 the_rest = line_info.the_rest
610 esc = line_info.esc
610 esc = line_info.esc
611 continue_prompt = line_info.continue_prompt
611 continue_prompt = line_info.continue_prompt
612 obj = line_info.ofind(self.shell)['obj']
612 obj = line_info.ofind(self.shell)['obj']
613
613
614 # This should only be active for single-line input!
614 # This should only be active for single-line input!
615 if continue_prompt:
615 if continue_prompt:
616 return line
616 return line
617
617
618 force_auto = isinstance(obj, IPyAutocall)
618 force_auto = isinstance(obj, IPyAutocall)
619
619
620 # User objects sometimes raise exceptions on attribute access other
620 # User objects sometimes raise exceptions on attribute access other
621 # than AttributeError (we've seen it in the past), so it's safest to be
621 # than AttributeError (we've seen it in the past), so it's safest to be
622 # ultra-conservative here and catch all.
622 # ultra-conservative here and catch all.
623 try:
623 try:
624 auto_rewrite = obj.rewrite
624 auto_rewrite = obj.rewrite
625 except Exception:
625 except Exception:
626 auto_rewrite = True
626 auto_rewrite = True
627
627
628 if esc == ESC_QUOTE:
628 if esc == ESC_QUOTE:
629 # Auto-quote splitting on whitespace
629 # Auto-quote splitting on whitespace
630 newcmd = '%s("%s")' % (ifun,'", "'.join(the_rest.split()) )
630 newcmd = '%s("%s")' % (ifun,'", "'.join(the_rest.split()) )
631 elif esc == ESC_QUOTE2:
631 elif esc == ESC_QUOTE2:
632 # Auto-quote whole string
632 # Auto-quote whole string
633 newcmd = '%s("%s")' % (ifun,the_rest)
633 newcmd = '%s("%s")' % (ifun,the_rest)
634 elif esc == ESC_PAREN:
634 elif esc == ESC_PAREN:
635 newcmd = '%s(%s)' % (ifun,",".join(the_rest.split()))
635 newcmd = '%s(%s)' % (ifun,",".join(the_rest.split()))
636 else:
636 else:
637 # Auto-paren.
637 # Auto-paren.
638 if force_auto:
638 if force_auto:
639 # Don't rewrite if it is already a call.
639 # Don't rewrite if it is already a call.
640 do_rewrite = not the_rest.startswith('(')
640 do_rewrite = not the_rest.startswith('(')
641 else:
641 else:
642 if not the_rest:
642 if not the_rest:
643 # We only apply it to argument-less calls if the autocall
643 # We only apply it to argument-less calls if the autocall
644 # parameter is set to 2.
644 # parameter is set to 2.
645 do_rewrite = (self.shell.autocall >= 2)
645 do_rewrite = (self.shell.autocall >= 2)
646 elif the_rest.startswith('[') and hasattr(obj, '__getitem__'):
646 elif the_rest.startswith('[') and hasattr(obj, '__getitem__'):
647 # Don't autocall in this case: item access for an object
647 # Don't autocall in this case: item access for an object
648 # which is BOTH callable and implements __getitem__.
648 # which is BOTH callable and implements __getitem__.
649 do_rewrite = False
649 do_rewrite = False
650 else:
650 else:
651 do_rewrite = True
651 do_rewrite = True
652
652
653 # Figure out the rewritten command
653 # Figure out the rewritten command
654 if do_rewrite:
654 if do_rewrite:
655 if the_rest.endswith(';'):
655 if the_rest.endswith(';'):
656 newcmd = '%s(%s);' % (ifun.rstrip(),the_rest[:-1])
656 newcmd = '%s(%s);' % (ifun.rstrip(),the_rest[:-1])
657 else:
657 else:
658 newcmd = '%s(%s)' % (ifun.rstrip(), the_rest)
658 newcmd = '%s(%s)' % (ifun.rstrip(), the_rest)
659 else:
659 else:
660 normal_handler = self.prefilter_manager.get_handler_by_name('normal')
660 normal_handler = self.prefilter_manager.get_handler_by_name('normal')
661 return normal_handler.handle(line_info)
661 return normal_handler.handle(line_info)
662
662
663 # Display the rewritten call
663 # Display the rewritten call
664 if auto_rewrite:
664 if auto_rewrite:
665 self.shell.auto_rewrite_input(newcmd)
665 self.shell.auto_rewrite_input(newcmd)
666
666
667 return newcmd
667 return newcmd
668
668
669
669
670 class EmacsHandler(PrefilterHandler):
670 class EmacsHandler(PrefilterHandler):
671
671
672 handler_name = Unicode('emacs')
672 handler_name = Unicode('emacs')
673 esc_strings = List([])
673 esc_strings = List([])
674
674
675 def handle(self, line_info):
675 def handle(self, line_info):
676 """Handle input lines marked by python-mode."""
676 """Handle input lines marked by python-mode."""
677
677
678 # Currently, nothing is done. Later more functionality can be added
678 # Currently, nothing is done. Later more functionality can be added
679 # here if needed.
679 # here if needed.
680
680
681 # The input cache shouldn't be updated
681 # The input cache shouldn't be updated
682 return line_info.line
682 return line_info.line
683
683
684
684
685 #-----------------------------------------------------------------------------
685 #-----------------------------------------------------------------------------
686 # Defaults
686 # Defaults
687 #-----------------------------------------------------------------------------
687 #-----------------------------------------------------------------------------
688
688
689
689
690 _default_transformers = [
690 _default_transformers = [
691 ]
691 ]
692
692
693 _default_checkers = [
693 _default_checkers = [
694 EmacsChecker,
694 EmacsChecker,
695 MacroChecker,
695 MacroChecker,
696 IPyAutocallChecker,
696 IPyAutocallChecker,
697 AssignmentChecker,
697 AssignmentChecker,
698 AutoMagicChecker,
698 AutoMagicChecker,
699 PythonOpsChecker,
699 PythonOpsChecker,
700 AutocallChecker
700 AutocallChecker
701 ]
701 ]
702
702
703 _default_handlers = [
703 _default_handlers = [
704 PrefilterHandler,
704 PrefilterHandler,
705 MacroHandler,
705 MacroHandler,
706 MagicHandler,
706 MagicHandler,
707 AutoHandler,
707 AutoHandler,
708 EmacsHandler
708 EmacsHandler
709 ]
709 ]
@@ -1,119 +1,119 b''
1 # -*- coding: utf-8 -*-
1 # -*- coding: utf-8 -*-
2 """Release data for the IPython project."""
2 """Release data for the IPython project."""
3
3
4 #-----------------------------------------------------------------------------
4 #-----------------------------------------------------------------------------
5 # Copyright (c) 2008, IPython Development Team.
5 # Copyright (c) 2008, IPython Development Team.
6 # Copyright (c) 2001, Fernando Perez <fernando.perez@colorado.edu>
6 # Copyright (c) 2001, Fernando Perez <fernando.perez@colorado.edu>
7 # Copyright (c) 2001, Janko Hauser <jhauser@zscout.de>
7 # Copyright (c) 2001, Janko Hauser <jhauser@zscout.de>
8 # Copyright (c) 2001, Nathaniel Gray <n8gray@caltech.edu>
8 # Copyright (c) 2001, Nathaniel Gray <n8gray@caltech.edu>
9 #
9 #
10 # Distributed under the terms of the Modified BSD License.
10 # Distributed under the terms of the Modified BSD License.
11 #
11 #
12 # The full license is in the file COPYING.txt, distributed with this software.
12 # The full license is in the file COPYING.txt, distributed with this software.
13 #-----------------------------------------------------------------------------
13 #-----------------------------------------------------------------------------
14
14
15 # Name of the package for release purposes. This is the name which labels
15 # Name of the package for release purposes. This is the name which labels
16 # the tarballs and RPMs made by distutils, so it's best to lowercase it.
16 # the tarballs and RPMs made by distutils, so it's best to lowercase it.
17 name = 'ipython'
17 name = 'ipython'
18
18
19 # IPython version information. An empty _version_extra corresponds to a full
19 # IPython version information. An empty _version_extra corresponds to a full
20 # release. 'dev' as a _version_extra string means this is a development
20 # release. 'dev' as a _version_extra string means this is a development
21 # version
21 # version
22 _version_major = 7
22 _version_major = 7
23 _version_minor = 0
23 _version_minor = 0
24 _version_patch = 0
24 _version_patch = 0
25 _version_extra = '.dev'
25 _version_extra = '.dev'
26 # _version_extra = 'rc2'
26 # _version_extra = 'rc2'
27 # _version_extra = '' # Uncomment this for full releases
27 # _version_extra = '' # Uncomment this for full releases
28
28
29 # Construct full version string from these.
29 # Construct full version string from these.
30 _ver = [_version_major, _version_minor, _version_patch]
30 _ver = [_version_major, _version_minor, _version_patch]
31
31
32 __version__ = '.'.join(map(str, _ver))
32 __version__ = '.'.join(map(str, _ver))
33 if _version_extra:
33 if _version_extra:
34 __version__ = __version__ + _version_extra
34 __version__ = __version__ + _version_extra
35
35
36 version = __version__ # backwards compatibility name
36 version = __version__ # backwards compatibility name
37 version_info = (_version_major, _version_minor, _version_patch, _version_extra)
37 version_info = (_version_major, _version_minor, _version_patch, _version_extra)
38
38
39 # Change this when incrementing the kernel protocol version
39 # Change this when incrementing the kernel protocol version
40 kernel_protocol_version_info = (5, 0)
40 kernel_protocol_version_info = (5, 0)
41 kernel_protocol_version = "%i.%i" % kernel_protocol_version_info
41 kernel_protocol_version = "%i.%i" % kernel_protocol_version_info
42
42
43 description = "IPython: Productive Interactive Computing"
43 description = "IPython: Productive Interactive Computing"
44
44
45 long_description = \
45 long_description = \
46 """
46 """
47 IPython provides a rich toolkit to help you make the most out of using Python
47 IPython provides a rich toolkit to help you make the most out of using Python
48 interactively. Its main components are:
48 interactively. Its main components are:
49
49
50 * A powerful interactive Python shell
50 * A powerful interactive Python shell
51 * A `Jupyter <http://jupyter.org/>`_ kernel to work with Python code in Jupyter
51 * A `Jupyter <https://jupyter.org/>`_ kernel to work with Python code in Jupyter
52 notebooks and other interactive frontends.
52 notebooks and other interactive frontends.
53
53
54 The enhanced interactive Python shells have the following main features:
54 The enhanced interactive Python shells have the following main features:
55
55
56 * Comprehensive object introspection.
56 * Comprehensive object introspection.
57
57
58 * Input history, persistent across sessions.
58 * Input history, persistent across sessions.
59
59
60 * Caching of output results during a session with automatically generated
60 * Caching of output results during a session with automatically generated
61 references.
61 references.
62
62
63 * Extensible tab completion, with support by default for completion of python
63 * Extensible tab completion, with support by default for completion of python
64 variables and keywords, filenames and function keywords.
64 variables and keywords, filenames and function keywords.
65
65
66 * Extensible system of 'magic' commands for controlling the environment and
66 * Extensible system of 'magic' commands for controlling the environment and
67 performing many tasks related either to IPython or the operating system.
67 performing many tasks related either to IPython or the operating system.
68
68
69 * A rich configuration system with easy switching between different setups
69 * A rich configuration system with easy switching between different setups
70 (simpler than changing $PYTHONSTARTUP environment variables every time).
70 (simpler than changing $PYTHONSTARTUP environment variables every time).
71
71
72 * Session logging and reloading.
72 * Session logging and reloading.
73
73
74 * Extensible syntax processing for special purpose situations.
74 * Extensible syntax processing for special purpose situations.
75
75
76 * Access to the system shell with user-extensible alias system.
76 * Access to the system shell with user-extensible alias system.
77
77
78 * Easily embeddable in other Python programs and GUIs.
78 * Easily embeddable in other Python programs and GUIs.
79
79
80 * Integrated access to the pdb debugger and the Python profiler.
80 * Integrated access to the pdb debugger and the Python profiler.
81
81
82 The latest development version is always available from IPython's `GitHub
82 The latest development version is always available from IPython's `GitHub
83 site <http://github.com/ipython>`_.
83 site <http://github.com/ipython>`_.
84 """
84 """
85
85
86 license = 'BSD'
86 license = 'BSD'
87
87
88 authors = {'Fernando' : ('Fernando Perez','fperez.net@gmail.com'),
88 authors = {'Fernando' : ('Fernando Perez','fperez.net@gmail.com'),
89 'Janko' : ('Janko Hauser','jhauser@zscout.de'),
89 'Janko' : ('Janko Hauser','jhauser@zscout.de'),
90 'Nathan' : ('Nathaniel Gray','n8gray@caltech.edu'),
90 'Nathan' : ('Nathaniel Gray','n8gray@caltech.edu'),
91 'Ville' : ('Ville Vainio','vivainio@gmail.com'),
91 'Ville' : ('Ville Vainio','vivainio@gmail.com'),
92 'Brian' : ('Brian E Granger', 'ellisonbg@gmail.com'),
92 'Brian' : ('Brian E Granger', 'ellisonbg@gmail.com'),
93 'Min' : ('Min Ragan-Kelley', 'benjaminrk@gmail.com'),
93 'Min' : ('Min Ragan-Kelley', 'benjaminrk@gmail.com'),
94 'Thomas' : ('Thomas A. Kluyver', 'takowl@gmail.com'),
94 'Thomas' : ('Thomas A. Kluyver', 'takowl@gmail.com'),
95 'Jorgen' : ('Jorgen Stenarson', 'jorgen.stenarson@bostream.nu'),
95 'Jorgen' : ('Jorgen Stenarson', 'jorgen.stenarson@bostream.nu'),
96 'Matthias' : ('Matthias Bussonnier', 'bussonniermatthias@gmail.com'),
96 'Matthias' : ('Matthias Bussonnier', 'bussonniermatthias@gmail.com'),
97 }
97 }
98
98
99 author = 'The IPython Development Team'
99 author = 'The IPython Development Team'
100
100
101 author_email = 'ipython-dev@python.org'
101 author_email = 'ipython-dev@python.org'
102
102
103 url = 'https://ipython.org'
103 url = 'https://ipython.org'
104
104
105
105
106 platforms = ['Linux','Mac OSX','Windows']
106 platforms = ['Linux','Mac OSX','Windows']
107
107
108 keywords = ['Interactive','Interpreter','Shell', 'Embedding']
108 keywords = ['Interactive','Interpreter','Shell', 'Embedding']
109
109
110 classifiers = [
110 classifiers = [
111 'Framework :: IPython',
111 'Framework :: IPython',
112 'Intended Audience :: Developers',
112 'Intended Audience :: Developers',
113 'Intended Audience :: Science/Research',
113 'Intended Audience :: Science/Research',
114 'License :: OSI Approved :: BSD License',
114 'License :: OSI Approved :: BSD License',
115 'Programming Language :: Python',
115 'Programming Language :: Python',
116 'Programming Language :: Python :: 3',
116 'Programming Language :: Python :: 3',
117 'Programming Language :: Python :: 3 :: Only',
117 'Programming Language :: Python :: 3 :: Only',
118 'Topic :: System :: Shells'
118 'Topic :: System :: Shells'
119 ]
119 ]
@@ -1,137 +1,137 b''
1 # encoding: utf-8
1 # encoding: utf-8
2 """
2 """
3 Simple utility for splitting user input. This is used by both inputsplitter and
3 Simple utility for splitting user input. This is used by both inputsplitter and
4 prefilter.
4 prefilter.
5
5
6 Authors:
6 Authors:
7
7
8 * Brian Granger
8 * Brian Granger
9 * Fernando Perez
9 * Fernando Perez
10 """
10 """
11
11
12 #-----------------------------------------------------------------------------
12 #-----------------------------------------------------------------------------
13 # Copyright (C) 2008-2011 The IPython Development Team
13 # Copyright (C) 2008-2011 The IPython Development Team
14 #
14 #
15 # Distributed under the terms of the BSD License. The full license is in
15 # Distributed under the terms of the BSD License. The full license is in
16 # the file COPYING, distributed as part of this software.
16 # the file COPYING, distributed as part of this software.
17 #-----------------------------------------------------------------------------
17 #-----------------------------------------------------------------------------
18
18
19 #-----------------------------------------------------------------------------
19 #-----------------------------------------------------------------------------
20 # Imports
20 # Imports
21 #-----------------------------------------------------------------------------
21 #-----------------------------------------------------------------------------
22
22
23 import re
23 import re
24 import sys
24 import sys
25
25
26 from IPython.utils import py3compat
26 from IPython.utils import py3compat
27 from IPython.utils.encoding import get_stream_enc
27 from IPython.utils.encoding import get_stream_enc
28
28
29 #-----------------------------------------------------------------------------
29 #-----------------------------------------------------------------------------
30 # Main function
30 # Main function
31 #-----------------------------------------------------------------------------
31 #-----------------------------------------------------------------------------
32
32
33 # RegExp for splitting line contents into pre-char//first word-method//rest.
33 # RegExp for splitting line contents into pre-char//first word-method//rest.
34 # For clarity, each group in on one line.
34 # For clarity, each group in on one line.
35
35
36 # WARNING: update the regexp if the escapes in interactiveshell are changed, as
36 # WARNING: update the regexp if the escapes in interactiveshell are changed, as
37 # they are hardwired in.
37 # they are hardwired in.
38
38
39 # Although it's not solely driven by the regex, note that:
39 # Although it's not solely driven by the regex, note that:
40 # ,;/% only trigger if they are the first character on the line
40 # ,;/% only trigger if they are the first character on the line
41 # ! and !! trigger if they are first char(s) *or* follow an indent
41 # ! and !! trigger if they are first char(s) *or* follow an indent
42 # ? triggers as first or last char.
42 # ? triggers as first or last char.
43
43
44 line_split = re.compile("""
44 line_split = re.compile(r"""
45 ^(\s*) # any leading space
45 ^(\s*) # any leading space
46 ([,;/%]|!!?|\?\??)? # escape character or characters
46 ([,;/%]|!!?|\?\??)? # escape character or characters
47 \s*(%{0,2}[\w\.\*]*) # function/method, possibly with leading %
47 \s*(%{0,2}[\w\.\*]*) # function/method, possibly with leading %
48 # to correctly treat things like '?%magic'
48 # to correctly treat things like '?%magic'
49 (.*?$|$) # rest of line
49 (.*?$|$) # rest of line
50 """, re.VERBOSE)
50 """, re.VERBOSE)
51
51
52
52
53 def split_user_input(line, pattern=None):
53 def split_user_input(line, pattern=None):
54 """Split user input into initial whitespace, escape character, function part
54 """Split user input into initial whitespace, escape character, function part
55 and the rest.
55 and the rest.
56 """
56 """
57 # We need to ensure that the rest of this routine deals only with unicode
57 # We need to ensure that the rest of this routine deals only with unicode
58 encoding = get_stream_enc(sys.stdin, 'utf-8')
58 encoding = get_stream_enc(sys.stdin, 'utf-8')
59 line = py3compat.cast_unicode(line, encoding)
59 line = py3compat.cast_unicode(line, encoding)
60
60
61 if pattern is None:
61 if pattern is None:
62 pattern = line_split
62 pattern = line_split
63 match = pattern.match(line)
63 match = pattern.match(line)
64 if not match:
64 if not match:
65 # print "match failed for line '%s'" % line
65 # print "match failed for line '%s'" % line
66 try:
66 try:
67 ifun, the_rest = line.split(None,1)
67 ifun, the_rest = line.split(None,1)
68 except ValueError:
68 except ValueError:
69 # print "split failed for line '%s'" % line
69 # print "split failed for line '%s'" % line
70 ifun, the_rest = line, u''
70 ifun, the_rest = line, u''
71 pre = re.match('^(\s*)(.*)',line).groups()[0]
71 pre = re.match(r'^(\s*)(.*)',line).groups()[0]
72 esc = ""
72 esc = ""
73 else:
73 else:
74 pre, esc, ifun, the_rest = match.groups()
74 pre, esc, ifun, the_rest = match.groups()
75
75
76 #print 'line:<%s>' % line # dbg
76 #print 'line:<%s>' % line # dbg
77 #print 'pre <%s> ifun <%s> rest <%s>' % (pre,ifun.strip(),the_rest) # dbg
77 #print 'pre <%s> ifun <%s> rest <%s>' % (pre,ifun.strip(),the_rest) # dbg
78 return pre, esc or '', ifun.strip(), the_rest.lstrip()
78 return pre, esc or '', ifun.strip(), the_rest.lstrip()
79
79
80
80
81 class LineInfo(object):
81 class LineInfo(object):
82 """A single line of input and associated info.
82 """A single line of input and associated info.
83
83
84 Includes the following as properties:
84 Includes the following as properties:
85
85
86 line
86 line
87 The original, raw line
87 The original, raw line
88
88
89 continue_prompt
89 continue_prompt
90 Is this line a continuation in a sequence of multiline input?
90 Is this line a continuation in a sequence of multiline input?
91
91
92 pre
92 pre
93 Any leading whitespace.
93 Any leading whitespace.
94
94
95 esc
95 esc
96 The escape character(s) in pre or the empty string if there isn't one.
96 The escape character(s) in pre or the empty string if there isn't one.
97 Note that '!!' and '??' are possible values for esc. Otherwise it will
97 Note that '!!' and '??' are possible values for esc. Otherwise it will
98 always be a single character.
98 always be a single character.
99
99
100 ifun
100 ifun
101 The 'function part', which is basically the maximal initial sequence
101 The 'function part', which is basically the maximal initial sequence
102 of valid python identifiers and the '.' character. This is what is
102 of valid python identifiers and the '.' character. This is what is
103 checked for alias and magic transformations, used for auto-calling,
103 checked for alias and magic transformations, used for auto-calling,
104 etc. In contrast to Python identifiers, it may start with "%" and contain
104 etc. In contrast to Python identifiers, it may start with "%" and contain
105 "*".
105 "*".
106
106
107 the_rest
107 the_rest
108 Everything else on the line.
108 Everything else on the line.
109 """
109 """
110 def __init__(self, line, continue_prompt=False):
110 def __init__(self, line, continue_prompt=False):
111 self.line = line
111 self.line = line
112 self.continue_prompt = continue_prompt
112 self.continue_prompt = continue_prompt
113 self.pre, self.esc, self.ifun, self.the_rest = split_user_input(line)
113 self.pre, self.esc, self.ifun, self.the_rest = split_user_input(line)
114
114
115 self.pre_char = self.pre.strip()
115 self.pre_char = self.pre.strip()
116 if self.pre_char:
116 if self.pre_char:
117 self.pre_whitespace = '' # No whitespace allowed before esc chars
117 self.pre_whitespace = '' # No whitespace allowed before esc chars
118 else:
118 else:
119 self.pre_whitespace = self.pre
119 self.pre_whitespace = self.pre
120
120
121 def ofind(self, ip):
121 def ofind(self, ip):
122 """Do a full, attribute-walking lookup of the ifun in the various
122 """Do a full, attribute-walking lookup of the ifun in the various
123 namespaces for the given IPython InteractiveShell instance.
123 namespaces for the given IPython InteractiveShell instance.
124
124
125 Return a dict with keys: {found, obj, ospace, ismagic}
125 Return a dict with keys: {found, obj, ospace, ismagic}
126
126
127 Note: can cause state changes because of calling getattr, but should
127 Note: can cause state changes because of calling getattr, but should
128 only be run if autocall is on and if the line hasn't matched any
128 only be run if autocall is on and if the line hasn't matched any
129 other, less dangerous handlers.
129 other, less dangerous handlers.
130
130
131 Does cache the results of the call, so can be called multiple times
131 Does cache the results of the call, so can be called multiple times
132 without worrying about *further* damaging state.
132 without worrying about *further* damaging state.
133 """
133 """
134 return ip._ofind(self.ifun)
134 return ip._ofind(self.ifun)
135
135
136 def __str__(self):
136 def __str__(self):
137 return "LineInfo [%s|%s|%s|%s]" %(self.pre, self.esc, self.ifun, self.the_rest)
137 return "LineInfo [%s|%s|%s|%s]" %(self.pre, self.esc, self.ifun, self.the_rest)
@@ -1,161 +1,178 b''
1 # -*- coding: utf-8 -*-
1 # -*- coding: utf-8 -*-
2 """Tests for completerlib.
2 """Tests for completerlib.
3
3
4 """
4 """
5
5
6 #-----------------------------------------------------------------------------
6 #-----------------------------------------------------------------------------
7 # Imports
7 # Imports
8 #-----------------------------------------------------------------------------
8 #-----------------------------------------------------------------------------
9
9
10 import os
10 import os
11 import shutil
11 import shutil
12 import sys
12 import sys
13 import tempfile
13 import tempfile
14 import unittest
14 import unittest
15 from os.path import join
15 from os.path import join
16
16
17 import nose.tools as nt
17 import nose.tools as nt
18
18
19 from IPython.core.completerlib import magic_run_completer, module_completion
19 from IPython.core.completerlib import magic_run_completer, module_completion, try_import
20 from IPython.utils.tempdir import TemporaryDirectory
20 from IPython.utils.tempdir import TemporaryDirectory
21 from IPython.testing.decorators import onlyif_unicode_paths
21 from IPython.testing.decorators import onlyif_unicode_paths
22
22
23
23
24 class MockEvent(object):
24 class MockEvent(object):
25 def __init__(self, line):
25 def __init__(self, line):
26 self.line = line
26 self.line = line
27
27
28 #-----------------------------------------------------------------------------
28 #-----------------------------------------------------------------------------
29 # Test functions begin
29 # Test functions begin
30 #-----------------------------------------------------------------------------
30 #-----------------------------------------------------------------------------
31 class Test_magic_run_completer(unittest.TestCase):
31 class Test_magic_run_completer(unittest.TestCase):
32 files = [u"aao.py", u"a.py", u"b.py", u"aao.txt"]
32 files = [u"aao.py", u"a.py", u"b.py", u"aao.txt"]
33 dirs = [u"adir/", "bdir/"]
33 dirs = [u"adir/", "bdir/"]
34
34
35 def setUp(self):
35 def setUp(self):
36 self.BASETESTDIR = tempfile.mkdtemp()
36 self.BASETESTDIR = tempfile.mkdtemp()
37 for fil in self.files:
37 for fil in self.files:
38 with open(join(self.BASETESTDIR, fil), "w") as sfile:
38 with open(join(self.BASETESTDIR, fil), "w") as sfile:
39 sfile.write("pass\n")
39 sfile.write("pass\n")
40 for d in self.dirs:
40 for d in self.dirs:
41 os.mkdir(join(self.BASETESTDIR, d))
41 os.mkdir(join(self.BASETESTDIR, d))
42
42
43 self.oldpath = os.getcwd()
43 self.oldpath = os.getcwd()
44 os.chdir(self.BASETESTDIR)
44 os.chdir(self.BASETESTDIR)
45
45
46 def tearDown(self):
46 def tearDown(self):
47 os.chdir(self.oldpath)
47 os.chdir(self.oldpath)
48 shutil.rmtree(self.BASETESTDIR)
48 shutil.rmtree(self.BASETESTDIR)
49
49
50 def test_1(self):
50 def test_1(self):
51 """Test magic_run_completer, should match two alterntives
51 """Test magic_run_completer, should match two alterntives
52 """
52 """
53 event = MockEvent(u"%run a")
53 event = MockEvent(u"%run a")
54 mockself = None
54 mockself = None
55 match = set(magic_run_completer(mockself, event))
55 match = set(magic_run_completer(mockself, event))
56 self.assertEqual(match, {u"a.py", u"aao.py", u"adir/"})
56 self.assertEqual(match, {u"a.py", u"aao.py", u"adir/"})
57
57
58 def test_2(self):
58 def test_2(self):
59 """Test magic_run_completer, should match one alterntive
59 """Test magic_run_completer, should match one alterntive
60 """
60 """
61 event = MockEvent(u"%run aa")
61 event = MockEvent(u"%run aa")
62 mockself = None
62 mockself = None
63 match = set(magic_run_completer(mockself, event))
63 match = set(magic_run_completer(mockself, event))
64 self.assertEqual(match, {u"aao.py"})
64 self.assertEqual(match, {u"aao.py"})
65
65
66 def test_3(self):
66 def test_3(self):
67 """Test magic_run_completer with unterminated " """
67 """Test magic_run_completer with unterminated " """
68 event = MockEvent(u'%run "a')
68 event = MockEvent(u'%run "a')
69 mockself = None
69 mockself = None
70 match = set(magic_run_completer(mockself, event))
70 match = set(magic_run_completer(mockself, event))
71 self.assertEqual(match, {u"a.py", u"aao.py", u"adir/"})
71 self.assertEqual(match, {u"a.py", u"aao.py", u"adir/"})
72
72
73 def test_completion_more_args(self):
73 def test_completion_more_args(self):
74 event = MockEvent(u'%run a.py ')
74 event = MockEvent(u'%run a.py ')
75 match = set(magic_run_completer(None, event))
75 match = set(magic_run_completer(None, event))
76 self.assertEqual(match, set(self.files + self.dirs))
76 self.assertEqual(match, set(self.files + self.dirs))
77
77
78 def test_completion_in_dir(self):
78 def test_completion_in_dir(self):
79 # Github issue #3459
79 # Github issue #3459
80 event = MockEvent(u'%run a.py {}'.format(join(self.BASETESTDIR, 'a')))
80 event = MockEvent(u'%run a.py {}'.format(join(self.BASETESTDIR, 'a')))
81 print(repr(event.line))
81 print(repr(event.line))
82 match = set(magic_run_completer(None, event))
82 match = set(magic_run_completer(None, event))
83 # We specifically use replace here rather than normpath, because
83 # We specifically use replace here rather than normpath, because
84 # at one point there were duplicates 'adir' and 'adir/', and normpath
84 # at one point there were duplicates 'adir' and 'adir/', and normpath
85 # would hide the failure for that.
85 # would hide the failure for that.
86 self.assertEqual(match, {join(self.BASETESTDIR, f).replace('\\','/')
86 self.assertEqual(match, {join(self.BASETESTDIR, f).replace('\\','/')
87 for f in (u'a.py', u'aao.py', u'aao.txt', u'adir/')})
87 for f in (u'a.py', u'aao.py', u'aao.txt', u'adir/')})
88
88
89 class Test_magic_run_completer_nonascii(unittest.TestCase):
89 class Test_magic_run_completer_nonascii(unittest.TestCase):
90 @onlyif_unicode_paths
90 @onlyif_unicode_paths
91 def setUp(self):
91 def setUp(self):
92 self.BASETESTDIR = tempfile.mkdtemp()
92 self.BASETESTDIR = tempfile.mkdtemp()
93 for fil in [u"aaø.py", u"a.py", u"b.py"]:
93 for fil in [u"aaø.py", u"a.py", u"b.py"]:
94 with open(join(self.BASETESTDIR, fil), "w") as sfile:
94 with open(join(self.BASETESTDIR, fil), "w") as sfile:
95 sfile.write("pass\n")
95 sfile.write("pass\n")
96 self.oldpath = os.getcwd()
96 self.oldpath = os.getcwd()
97 os.chdir(self.BASETESTDIR)
97 os.chdir(self.BASETESTDIR)
98
98
99 def tearDown(self):
99 def tearDown(self):
100 os.chdir(self.oldpath)
100 os.chdir(self.oldpath)
101 shutil.rmtree(self.BASETESTDIR)
101 shutil.rmtree(self.BASETESTDIR)
102
102
103 @onlyif_unicode_paths
103 @onlyif_unicode_paths
104 def test_1(self):
104 def test_1(self):
105 """Test magic_run_completer, should match two alterntives
105 """Test magic_run_completer, should match two alterntives
106 """
106 """
107 event = MockEvent(u"%run a")
107 event = MockEvent(u"%run a")
108 mockself = None
108 mockself = None
109 match = set(magic_run_completer(mockself, event))
109 match = set(magic_run_completer(mockself, event))
110 self.assertEqual(match, {u"a.py", u"aaø.py"})
110 self.assertEqual(match, {u"a.py", u"aaø.py"})
111
111
112 @onlyif_unicode_paths
112 @onlyif_unicode_paths
113 def test_2(self):
113 def test_2(self):
114 """Test magic_run_completer, should match one alterntive
114 """Test magic_run_completer, should match one alterntive
115 """
115 """
116 event = MockEvent(u"%run aa")
116 event = MockEvent(u"%run aa")
117 mockself = None
117 mockself = None
118 match = set(magic_run_completer(mockself, event))
118 match = set(magic_run_completer(mockself, event))
119 self.assertEqual(match, {u"aaø.py"})
119 self.assertEqual(match, {u"aaø.py"})
120
120
121 @onlyif_unicode_paths
121 @onlyif_unicode_paths
122 def test_3(self):
122 def test_3(self):
123 """Test magic_run_completer with unterminated " """
123 """Test magic_run_completer with unterminated " """
124 event = MockEvent(u'%run "a')
124 event = MockEvent(u'%run "a')
125 mockself = None
125 mockself = None
126 match = set(magic_run_completer(mockself, event))
126 match = set(magic_run_completer(mockself, event))
127 self.assertEqual(match, {u"a.py", u"aaø.py"})
127 self.assertEqual(match, {u"a.py", u"aaø.py"})
128
128
129 # module_completer:
129 # module_completer:
130
130
131 def test_import_invalid_module():
131 def test_import_invalid_module():
132 """Testing of issue https://github.com/ipython/ipython/issues/1107"""
132 """Testing of issue https://github.com/ipython/ipython/issues/1107"""
133 invalid_module_names = {'foo-bar', 'foo:bar', '10foo'}
133 invalid_module_names = {'foo-bar', 'foo:bar', '10foo'}
134 valid_module_names = {'foobar'}
134 valid_module_names = {'foobar'}
135 with TemporaryDirectory() as tmpdir:
135 with TemporaryDirectory() as tmpdir:
136 sys.path.insert( 0, tmpdir )
136 sys.path.insert( 0, tmpdir )
137 for name in invalid_module_names | valid_module_names:
137 for name in invalid_module_names | valid_module_names:
138 filename = os.path.join(tmpdir, name + '.py')
138 filename = os.path.join(tmpdir, name + '.py')
139 open(filename, 'w').close()
139 open(filename, 'w').close()
140
140
141 s = set( module_completion('import foo') )
141 s = set( module_completion('import foo') )
142 intersection = s.intersection(invalid_module_names)
142 intersection = s.intersection(invalid_module_names)
143 nt.assert_equal(intersection, set())
143 nt.assert_equal(intersection, set())
144
144
145 assert valid_module_names.issubset(s), valid_module_names.intersection(s)
145 assert valid_module_names.issubset(s), valid_module_names.intersection(s)
146
146
147
147
148 def test_bad_module_all():
148 def test_bad_module_all():
149 """Test module with invalid __all__
149 """Test module with invalid __all__
150
150
151 https://github.com/ipython/ipython/issues/9678
151 https://github.com/ipython/ipython/issues/9678
152 """
152 """
153 testsdir = os.path.dirname(__file__)
153 testsdir = os.path.dirname(__file__)
154 sys.path.insert(0, testsdir)
154 sys.path.insert(0, testsdir)
155 try:
155 try:
156 results = module_completion('from bad_all import ')
156 results = module_completion('from bad_all import ')
157 nt.assert_in('puppies', results)
157 nt.assert_in('puppies', results)
158 for r in results:
158 for r in results:
159 nt.assert_is_instance(r, str)
159 nt.assert_is_instance(r, str)
160 finally:
160 finally:
161 sys.path.remove(testsdir)
161 sys.path.remove(testsdir)
162
163
164 def test_module_without_init():
165 """
166 Test module without __init__.py.
167
168 https://github.com/ipython/ipython/issues/11226
169 """
170 fake_module_name = "foo"
171 with TemporaryDirectory() as tmpdir:
172 sys.path.insert(0, tmpdir)
173 try:
174 os.makedirs(os.path.join(tmpdir, fake_module_name))
175 s = try_import(mod=fake_module_name)
176 assert s == []
177 finally:
178 sys.path.remove(tmpdir)
@@ -1,393 +1,403 b''
1 # Copyright (c) IPython Development Team.
1 # Copyright (c) IPython Development Team.
2 # Distributed under the terms of the Modified BSD License.
2 # Distributed under the terms of the Modified BSD License.
3
3
4 import json
4 import json
5 import os
5 import os
6 import warnings
6 import warnings
7
7
8 from unittest import mock
8 from unittest import mock
9
9
10 import nose.tools as nt
10 import nose.tools as nt
11
11
12 from IPython.core import display
12 from IPython.core import display
13 from IPython.core.getipython import get_ipython
13 from IPython.core.getipython import get_ipython
14 from IPython.utils.io import capture_output
14 from IPython.utils.io import capture_output
15 from IPython.utils.tempdir import NamedFileInTemporaryDirectory
15 from IPython.utils.tempdir import NamedFileInTemporaryDirectory
16 from IPython import paths as ipath
16 from IPython import paths as ipath
17 from IPython.testing.tools import AssertPrints, AssertNotPrints
17 from IPython.testing.tools import AssertPrints, AssertNotPrints
18
18
19 import IPython.testing.decorators as dec
19 import IPython.testing.decorators as dec
20
20
21 def test_image_size():
21 def test_image_size():
22 """Simple test for display.Image(args, width=x,height=y)"""
22 """Simple test for display.Image(args, width=x,height=y)"""
23 thisurl = 'http://www.google.fr/images/srpr/logo3w.png'
23 thisurl = 'http://www.google.fr/images/srpr/logo3w.png'
24 img = display.Image(url=thisurl, width=200, height=200)
24 img = display.Image(url=thisurl, width=200, height=200)
25 nt.assert_equal(u'<img src="%s" width="200" height="200"/>' % (thisurl), img._repr_html_())
25 nt.assert_equal(u'<img src="%s" width="200" height="200"/>' % (thisurl), img._repr_html_())
26 img = display.Image(url=thisurl, metadata={'width':200, 'height':200})
26 img = display.Image(url=thisurl, metadata={'width':200, 'height':200})
27 nt.assert_equal(u'<img src="%s" width="200" height="200"/>' % (thisurl), img._repr_html_())
27 nt.assert_equal(u'<img src="%s" width="200" height="200"/>' % (thisurl), img._repr_html_())
28 img = display.Image(url=thisurl, width=200)
28 img = display.Image(url=thisurl, width=200)
29 nt.assert_equal(u'<img src="%s" width="200"/>' % (thisurl), img._repr_html_())
29 nt.assert_equal(u'<img src="%s" width="200"/>' % (thisurl), img._repr_html_())
30 img = display.Image(url=thisurl)
30 img = display.Image(url=thisurl)
31 nt.assert_equal(u'<img src="%s"/>' % (thisurl), img._repr_html_())
31 nt.assert_equal(u'<img src="%s"/>' % (thisurl), img._repr_html_())
32 img = display.Image(url=thisurl, unconfined=True)
32 img = display.Image(url=thisurl, unconfined=True)
33 nt.assert_equal(u'<img src="%s" class="unconfined"/>' % (thisurl), img._repr_html_())
33 nt.assert_equal(u'<img src="%s" class="unconfined"/>' % (thisurl), img._repr_html_())
34
34
35
35
36 def test_image_mimes():
36 def test_image_mimes():
37 fmt = get_ipython().display_formatter.format
37 fmt = get_ipython().display_formatter.format
38 for format in display.Image._ACCEPTABLE_EMBEDDINGS:
38 for format in display.Image._ACCEPTABLE_EMBEDDINGS:
39 mime = display.Image._MIMETYPES[format]
39 mime = display.Image._MIMETYPES[format]
40 img = display.Image(b'garbage', format=format)
40 img = display.Image(b'garbage', format=format)
41 data, metadata = fmt(img)
41 data, metadata = fmt(img)
42 nt.assert_equal(sorted(data), sorted([mime, 'text/plain']))
42 nt.assert_equal(sorted(data), sorted([mime, 'text/plain']))
43
43
44
44
45 def test_geojson():
45 def test_geojson():
46
46
47 gj = display.GeoJSON(data={
47 gj = display.GeoJSON(data={
48 "type": "Feature",
48 "type": "Feature",
49 "geometry": {
49 "geometry": {
50 "type": "Point",
50 "type": "Point",
51 "coordinates": [-81.327, 296.038]
51 "coordinates": [-81.327, 296.038]
52 },
52 },
53 "properties": {
53 "properties": {
54 "name": "Inca City"
54 "name": "Inca City"
55 }
55 }
56 },
56 },
57 url_template="http://s3-eu-west-1.amazonaws.com/whereonmars.cartodb.net/{basemap_id}/{z}/{x}/{y}.png",
57 url_template="http://s3-eu-west-1.amazonaws.com/whereonmars.cartodb.net/{basemap_id}/{z}/{x}/{y}.png",
58 layer_options={
58 layer_options={
59 "basemap_id": "celestia_mars-shaded-16k_global",
59 "basemap_id": "celestia_mars-shaded-16k_global",
60 "attribution": "Celestia/praesepe",
60 "attribution": "Celestia/praesepe",
61 "minZoom": 0,
61 "minZoom": 0,
62 "maxZoom": 18,
62 "maxZoom": 18,
63 })
63 })
64 nt.assert_equal(u'<IPython.core.display.GeoJSON object>', str(gj))
64 nt.assert_equal(u'<IPython.core.display.GeoJSON object>', str(gj))
65
65
66 def test_retina_png():
66 def test_retina_png():
67 here = os.path.dirname(__file__)
67 here = os.path.dirname(__file__)
68 img = display.Image(os.path.join(here, "2x2.png"), retina=True)
68 img = display.Image(os.path.join(here, "2x2.png"), retina=True)
69 nt.assert_equal(img.height, 1)
69 nt.assert_equal(img.height, 1)
70 nt.assert_equal(img.width, 1)
70 nt.assert_equal(img.width, 1)
71 data, md = img._repr_png_()
71 data, md = img._repr_png_()
72 nt.assert_equal(md['width'], 1)
72 nt.assert_equal(md['width'], 1)
73 nt.assert_equal(md['height'], 1)
73 nt.assert_equal(md['height'], 1)
74
74
75 def test_retina_jpeg():
75 def test_retina_jpeg():
76 here = os.path.dirname(__file__)
76 here = os.path.dirname(__file__)
77 img = display.Image(os.path.join(here, "2x2.jpg"), retina=True)
77 img = display.Image(os.path.join(here, "2x2.jpg"), retina=True)
78 nt.assert_equal(img.height, 1)
78 nt.assert_equal(img.height, 1)
79 nt.assert_equal(img.width, 1)
79 nt.assert_equal(img.width, 1)
80 data, md = img._repr_jpeg_()
80 data, md = img._repr_jpeg_()
81 nt.assert_equal(md['width'], 1)
81 nt.assert_equal(md['width'], 1)
82 nt.assert_equal(md['height'], 1)
82 nt.assert_equal(md['height'], 1)
83
83
84 def test_base64image():
84 def test_base64image():
85 display.Image("iVBORw0KGgoAAAANSUhEUgAAAAEAAAABAQMAAAAl21bKAAAAA1BMVEUAAACnej3aAAAAAWJLR0QAiAUdSAAAAAlwSFlzAAALEwAACxMBAJqcGAAAAAd0SU1FB94BCRQnOqNu0b4AAAAKSURBVAjXY2AAAAACAAHiIbwzAAAAAElFTkSuQmCC")
85 display.Image("iVBORw0KGgoAAAANSUhEUgAAAAEAAAABAQMAAAAl21bKAAAAA1BMVEUAAACnej3aAAAAAWJLR0QAiAUdSAAAAAlwSFlzAAALEwAACxMBAJqcGAAAAAd0SU1FB94BCRQnOqNu0b4AAAAKSURBVAjXY2AAAAACAAHiIbwzAAAAAElFTkSuQmCC")
86
86
87 def test_image_filename_defaults():
87 def test_image_filename_defaults():
88 '''test format constraint, and validity of jpeg and png'''
88 '''test format constraint, and validity of jpeg and png'''
89 tpath = ipath.get_ipython_package_dir()
89 tpath = ipath.get_ipython_package_dir()
90 nt.assert_raises(ValueError, display.Image, filename=os.path.join(tpath, 'testing/tests/badformat.zip'),
90 nt.assert_raises(ValueError, display.Image, filename=os.path.join(tpath, 'testing/tests/badformat.zip'),
91 embed=True)
91 embed=True)
92 nt.assert_raises(ValueError, display.Image)
92 nt.assert_raises(ValueError, display.Image)
93 nt.assert_raises(ValueError, display.Image, data='this is not an image', format='badformat', embed=True)
93 nt.assert_raises(ValueError, display.Image, data='this is not an image', format='badformat', embed=True)
94 # check boths paths to allow packages to test at build and install time
94 # check boths paths to allow packages to test at build and install time
95 imgfile = os.path.join(tpath, 'core/tests/2x2.png')
95 imgfile = os.path.join(tpath, 'core/tests/2x2.png')
96 img = display.Image(filename=imgfile)
96 img = display.Image(filename=imgfile)
97 nt.assert_equal('png', img.format)
97 nt.assert_equal('png', img.format)
98 nt.assert_is_not_none(img._repr_png_())
98 nt.assert_is_not_none(img._repr_png_())
99 img = display.Image(filename=os.path.join(tpath, 'testing/tests/logo.jpg'), embed=False)
99 img = display.Image(filename=os.path.join(tpath, 'testing/tests/logo.jpg'), embed=False)
100 nt.assert_equal('jpeg', img.format)
100 nt.assert_equal('jpeg', img.format)
101 nt.assert_is_none(img._repr_jpeg_())
101 nt.assert_is_none(img._repr_jpeg_())
102
102
103 def _get_inline_config():
103 def _get_inline_config():
104 from ipykernel.pylab.config import InlineBackend
104 from ipykernel.pylab.config import InlineBackend
105 return InlineBackend.instance()
105 return InlineBackend.instance()
106
106
107 @dec.skip_without('matplotlib')
107 @dec.skip_without('matplotlib')
108 def test_set_matplotlib_close():
108 def test_set_matplotlib_close():
109 cfg = _get_inline_config()
109 cfg = _get_inline_config()
110 cfg.close_figures = False
110 cfg.close_figures = False
111 display.set_matplotlib_close()
111 display.set_matplotlib_close()
112 assert cfg.close_figures
112 assert cfg.close_figures
113 display.set_matplotlib_close(False)
113 display.set_matplotlib_close(False)
114 assert not cfg.close_figures
114 assert not cfg.close_figures
115
115
116 _fmt_mime_map = {
116 _fmt_mime_map = {
117 'png': 'image/png',
117 'png': 'image/png',
118 'jpeg': 'image/jpeg',
118 'jpeg': 'image/jpeg',
119 'pdf': 'application/pdf',
119 'pdf': 'application/pdf',
120 'retina': 'image/png',
120 'retina': 'image/png',
121 'svg': 'image/svg+xml',
121 'svg': 'image/svg+xml',
122 }
122 }
123
123
124 @dec.skip_without('matplotlib')
124 @dec.skip_without('matplotlib')
125 def test_set_matplotlib_formats():
125 def test_set_matplotlib_formats():
126 from matplotlib.figure import Figure
126 from matplotlib.figure import Figure
127 formatters = get_ipython().display_formatter.formatters
127 formatters = get_ipython().display_formatter.formatters
128 for formats in [
128 for formats in [
129 ('png',),
129 ('png',),
130 ('pdf', 'svg'),
130 ('pdf', 'svg'),
131 ('jpeg', 'retina', 'png'),
131 ('jpeg', 'retina', 'png'),
132 (),
132 (),
133 ]:
133 ]:
134 active_mimes = {_fmt_mime_map[fmt] for fmt in formats}
134 active_mimes = {_fmt_mime_map[fmt] for fmt in formats}
135 display.set_matplotlib_formats(*formats)
135 display.set_matplotlib_formats(*formats)
136 for mime, f in formatters.items():
136 for mime, f in formatters.items():
137 if mime in active_mimes:
137 if mime in active_mimes:
138 nt.assert_in(Figure, f)
138 nt.assert_in(Figure, f)
139 else:
139 else:
140 nt.assert_not_in(Figure, f)
140 nt.assert_not_in(Figure, f)
141
141
142 @dec.skip_without('matplotlib')
142 @dec.skip_without('matplotlib')
143 def test_set_matplotlib_formats_kwargs():
143 def test_set_matplotlib_formats_kwargs():
144 from matplotlib.figure import Figure
144 from matplotlib.figure import Figure
145 ip = get_ipython()
145 ip = get_ipython()
146 cfg = _get_inline_config()
146 cfg = _get_inline_config()
147 cfg.print_figure_kwargs.update(dict(foo='bar'))
147 cfg.print_figure_kwargs.update(dict(foo='bar'))
148 kwargs = dict(quality=10)
148 kwargs = dict(quality=10)
149 display.set_matplotlib_formats('png', **kwargs)
149 display.set_matplotlib_formats('png', **kwargs)
150 formatter = ip.display_formatter.formatters['image/png']
150 formatter = ip.display_formatter.formatters['image/png']
151 f = formatter.lookup_by_type(Figure)
151 f = formatter.lookup_by_type(Figure)
152 cell = f.__closure__[0].cell_contents
152 cell = f.__closure__[0].cell_contents
153 expected = kwargs
153 expected = kwargs
154 expected.update(cfg.print_figure_kwargs)
154 expected.update(cfg.print_figure_kwargs)
155 nt.assert_equal(cell, expected)
155 nt.assert_equal(cell, expected)
156
156
157 def test_display_available():
157 def test_display_available():
158 """
158 """
159 Test that display is available without import
159 Test that display is available without import
160
160
161 We don't really care if it's in builtin or anything else, but it should
161 We don't really care if it's in builtin or anything else, but it should
162 always be available.
162 always be available.
163 """
163 """
164 ip = get_ipython()
164 ip = get_ipython()
165 with AssertNotPrints('NameError'):
165 with AssertNotPrints('NameError'):
166 ip.run_cell('display')
166 ip.run_cell('display')
167 try:
167 try:
168 ip.run_cell('del display')
168 ip.run_cell('del display')
169 except NameError:
169 except NameError:
170 pass # it's ok, it might be in builtins
170 pass # it's ok, it might be in builtins
171 # even if deleted it should be back
171 # even if deleted it should be back
172 with AssertNotPrints('NameError'):
172 with AssertNotPrints('NameError'):
173 ip.run_cell('display')
173 ip.run_cell('display')
174
174
175 def test_textdisplayobj_pretty_repr():
175 def test_textdisplayobj_pretty_repr():
176 p = display.Pretty("This is a simple test")
176 p = display.Pretty("This is a simple test")
177 nt.assert_equal(repr(p), '<IPython.core.display.Pretty object>')
177 nt.assert_equal(repr(p), '<IPython.core.display.Pretty object>')
178 nt.assert_equal(p.data, 'This is a simple test')
178 nt.assert_equal(p.data, 'This is a simple test')
179
179
180 p._show_mem_addr = True
180 p._show_mem_addr = True
181 nt.assert_equal(repr(p), object.__repr__(p))
181 nt.assert_equal(repr(p), object.__repr__(p))
182
182
183 def test_displayobject_repr():
183 def test_displayobject_repr():
184 h = display.HTML('<br />')
184 h = display.HTML('<br />')
185 nt.assert_equal(repr(h), '<IPython.core.display.HTML object>')
185 nt.assert_equal(repr(h), '<IPython.core.display.HTML object>')
186 h._show_mem_addr = True
186 h._show_mem_addr = True
187 nt.assert_equal(repr(h), object.__repr__(h))
187 nt.assert_equal(repr(h), object.__repr__(h))
188 h._show_mem_addr = False
188 h._show_mem_addr = False
189 nt.assert_equal(repr(h), '<IPython.core.display.HTML object>')
189 nt.assert_equal(repr(h), '<IPython.core.display.HTML object>')
190
190
191 j = display.Javascript('')
191 j = display.Javascript('')
192 nt.assert_equal(repr(j), '<IPython.core.display.Javascript object>')
192 nt.assert_equal(repr(j), '<IPython.core.display.Javascript object>')
193 j._show_mem_addr = True
193 j._show_mem_addr = True
194 nt.assert_equal(repr(j), object.__repr__(j))
194 nt.assert_equal(repr(j), object.__repr__(j))
195 j._show_mem_addr = False
195 j._show_mem_addr = False
196 nt.assert_equal(repr(j), '<IPython.core.display.Javascript object>')
196 nt.assert_equal(repr(j), '<IPython.core.display.Javascript object>')
197
197
198 def test_progress():
198 def test_progress():
199 p = display.ProgressBar(10)
199 p = display.ProgressBar(10)
200 nt.assert_in('0/10',repr(p))
200 nt.assert_in('0/10',repr(p))
201 p.html_width = '100%'
201 p.html_width = '100%'
202 p.progress = 5
202 p.progress = 5
203 nt.assert_equal(p._repr_html_(), "<progress style='width:100%' max='10' value='5'></progress>")
203 nt.assert_equal(p._repr_html_(), "<progress style='width:100%' max='10' value='5'></progress>")
204
204
205 def test_progress_iter():
205 def test_progress_iter():
206 with capture_output(display=False) as captured:
206 with capture_output(display=False) as captured:
207 for i in display.ProgressBar(5):
207 for i in display.ProgressBar(5):
208 out = captured.stdout
208 out = captured.stdout
209 nt.assert_in('{0}/5'.format(i), out)
209 nt.assert_in('{0}/5'.format(i), out)
210 out = captured.stdout
210 out = captured.stdout
211 nt.assert_in('5/5', out)
211 nt.assert_in('5/5', out)
212
212
213 def test_json():
213 def test_json():
214 d = {'a': 5}
214 d = {'a': 5}
215 lis = [d]
215 lis = [d]
216 md = {'expanded': False}
216 metadata = [
217 md2 = {'expanded': True}
217 {'expanded': False, 'root': 'root'},
218 j = display.JSON(d)
218 {'expanded': True, 'root': 'root'},
219 j2 = display.JSON(d, expanded=True)
219 {'expanded': False, 'root': 'custom'},
220 nt.assert_equal(j._repr_json_(), (d, md))
220 {'expanded': True, 'root': 'custom'},
221 nt.assert_equal(j2._repr_json_(), (d, md2))
221 ]
222 json_objs = [
223 display.JSON(d),
224 display.JSON(d, expanded=True),
225 display.JSON(d, root='custom'),
226 display.JSON(d, expanded=True, root='custom'),
227 ]
228 for j, md in zip(json_objs, metadata):
229 nt.assert_equal(j._repr_json_(), (d, md))
222
230
223 with warnings.catch_warnings(record=True) as w:
231 with warnings.catch_warnings(record=True) as w:
224 warnings.simplefilter("always")
232 warnings.simplefilter("always")
225 j = display.JSON(json.dumps(d))
233 j = display.JSON(json.dumps(d))
226 nt.assert_equal(len(w), 1)
234 nt.assert_equal(len(w), 1)
227 nt.assert_equal(j._repr_json_(), (d, md))
235 nt.assert_equal(j._repr_json_(), (d, metadata[0]))
228 nt.assert_equal(j2._repr_json_(), (d, md2))
236
229
237 json_objs = [
230 j = display.JSON(lis)
238 display.JSON(lis),
231 j2 = display.JSON(lis, expanded=True)
239 display.JSON(lis, expanded=True),
232 nt.assert_equal(j._repr_json_(), (lis, md))
240 display.JSON(lis, root='custom'),
233 nt.assert_equal(j2._repr_json_(), (lis, md2))
241 display.JSON(lis, expanded=True, root='custom'),
242 ]
243 for j, md in zip(json_objs, metadata):
244 nt.assert_equal(j._repr_json_(), (lis, md))
234
245
235 with warnings.catch_warnings(record=True) as w:
246 with warnings.catch_warnings(record=True) as w:
236 warnings.simplefilter("always")
247 warnings.simplefilter("always")
237 j = display.JSON(json.dumps(lis))
248 j = display.JSON(json.dumps(lis))
238 nt.assert_equal(len(w), 1)
249 nt.assert_equal(len(w), 1)
239 nt.assert_equal(j._repr_json_(), (lis, md))
250 nt.assert_equal(j._repr_json_(), (lis, metadata[0]))
240 nt.assert_equal(j2._repr_json_(), (lis, md2))
241
251
242 def test_video_embedding():
252 def test_video_embedding():
243 """use a tempfile, with dummy-data, to ensure that video embedding doesn't crash"""
253 """use a tempfile, with dummy-data, to ensure that video embedding doesn't crash"""
244 v = display.Video("http://ignored")
254 v = display.Video("http://ignored")
245 assert not v.embed
255 assert not v.embed
246 html = v._repr_html_()
256 html = v._repr_html_()
247 nt.assert_not_in('src="data:', html)
257 nt.assert_not_in('src="data:', html)
248 nt.assert_in('src="http://ignored"', html)
258 nt.assert_in('src="http://ignored"', html)
249
259
250 with nt.assert_raises(ValueError):
260 with nt.assert_raises(ValueError):
251 v = display.Video(b'abc')
261 v = display.Video(b'abc')
252
262
253 with NamedFileInTemporaryDirectory('test.mp4') as f:
263 with NamedFileInTemporaryDirectory('test.mp4') as f:
254 f.write(b'abc')
264 f.write(b'abc')
255 f.close()
265 f.close()
256
266
257 v = display.Video(f.name)
267 v = display.Video(f.name)
258 assert not v.embed
268 assert not v.embed
259 html = v._repr_html_()
269 html = v._repr_html_()
260 nt.assert_not_in('src="data:', html)
270 nt.assert_not_in('src="data:', html)
261
271
262 v = display.Video(f.name, embed=True)
272 v = display.Video(f.name, embed=True)
263 html = v._repr_html_()
273 html = v._repr_html_()
264 nt.assert_in('src="data:video/mp4;base64,YWJj"',html)
274 nt.assert_in('src="data:video/mp4;base64,YWJj"',html)
265
275
266 v = display.Video(f.name, embed=True, mimetype='video/other')
276 v = display.Video(f.name, embed=True, mimetype='video/other')
267 html = v._repr_html_()
277 html = v._repr_html_()
268 nt.assert_in('src="data:video/other;base64,YWJj"',html)
278 nt.assert_in('src="data:video/other;base64,YWJj"',html)
269
279
270 v = display.Video(b'abc', embed=True, mimetype='video/mp4')
280 v = display.Video(b'abc', embed=True, mimetype='video/mp4')
271 html = v._repr_html_()
281 html = v._repr_html_()
272 nt.assert_in('src="data:video/mp4;base64,YWJj"',html)
282 nt.assert_in('src="data:video/mp4;base64,YWJj"',html)
273
283
274 v = display.Video(u'YWJj', embed=True, mimetype='video/xyz')
284 v = display.Video(u'YWJj', embed=True, mimetype='video/xyz')
275 html = v._repr_html_()
285 html = v._repr_html_()
276 nt.assert_in('src="data:video/xyz;base64,YWJj"',html)
286 nt.assert_in('src="data:video/xyz;base64,YWJj"',html)
277
287
278 def test_html_metadata():
288 def test_html_metadata():
279 s = "<h1>Test</h1>"
289 s = "<h1>Test</h1>"
280 h = display.HTML(s, metadata={"isolated": True})
290 h = display.HTML(s, metadata={"isolated": True})
281 nt.assert_equal(h._repr_html_(), (s, {"isolated": True}))
291 nt.assert_equal(h._repr_html_(), (s, {"isolated": True}))
282
292
283 def test_display_id():
293 def test_display_id():
284 ip = get_ipython()
294 ip = get_ipython()
285 with mock.patch.object(ip.display_pub, 'publish') as pub:
295 with mock.patch.object(ip.display_pub, 'publish') as pub:
286 handle = display.display('x')
296 handle = display.display('x')
287 nt.assert_is(handle, None)
297 nt.assert_is(handle, None)
288 handle = display.display('y', display_id='secret')
298 handle = display.display('y', display_id='secret')
289 nt.assert_is_instance(handle, display.DisplayHandle)
299 nt.assert_is_instance(handle, display.DisplayHandle)
290 handle2 = display.display('z', display_id=True)
300 handle2 = display.display('z', display_id=True)
291 nt.assert_is_instance(handle2, display.DisplayHandle)
301 nt.assert_is_instance(handle2, display.DisplayHandle)
292 nt.assert_not_equal(handle.display_id, handle2.display_id)
302 nt.assert_not_equal(handle.display_id, handle2.display_id)
293
303
294 nt.assert_equal(pub.call_count, 3)
304 nt.assert_equal(pub.call_count, 3)
295 args, kwargs = pub.call_args_list[0]
305 args, kwargs = pub.call_args_list[0]
296 nt.assert_equal(args, ())
306 nt.assert_equal(args, ())
297 nt.assert_equal(kwargs, {
307 nt.assert_equal(kwargs, {
298 'data': {
308 'data': {
299 'text/plain': repr('x')
309 'text/plain': repr('x')
300 },
310 },
301 'metadata': {},
311 'metadata': {},
302 })
312 })
303 args, kwargs = pub.call_args_list[1]
313 args, kwargs = pub.call_args_list[1]
304 nt.assert_equal(args, ())
314 nt.assert_equal(args, ())
305 nt.assert_equal(kwargs, {
315 nt.assert_equal(kwargs, {
306 'data': {
316 'data': {
307 'text/plain': repr('y')
317 'text/plain': repr('y')
308 },
318 },
309 'metadata': {},
319 'metadata': {},
310 'transient': {
320 'transient': {
311 'display_id': handle.display_id,
321 'display_id': handle.display_id,
312 },
322 },
313 })
323 })
314 args, kwargs = pub.call_args_list[2]
324 args, kwargs = pub.call_args_list[2]
315 nt.assert_equal(args, ())
325 nt.assert_equal(args, ())
316 nt.assert_equal(kwargs, {
326 nt.assert_equal(kwargs, {
317 'data': {
327 'data': {
318 'text/plain': repr('z')
328 'text/plain': repr('z')
319 },
329 },
320 'metadata': {},
330 'metadata': {},
321 'transient': {
331 'transient': {
322 'display_id': handle2.display_id,
332 'display_id': handle2.display_id,
323 },
333 },
324 })
334 })
325
335
326
336
327 def test_update_display():
337 def test_update_display():
328 ip = get_ipython()
338 ip = get_ipython()
329 with mock.patch.object(ip.display_pub, 'publish') as pub:
339 with mock.patch.object(ip.display_pub, 'publish') as pub:
330 with nt.assert_raises(TypeError):
340 with nt.assert_raises(TypeError):
331 display.update_display('x')
341 display.update_display('x')
332 display.update_display('x', display_id='1')
342 display.update_display('x', display_id='1')
333 display.update_display('y', display_id='2')
343 display.update_display('y', display_id='2')
334 args, kwargs = pub.call_args_list[0]
344 args, kwargs = pub.call_args_list[0]
335 nt.assert_equal(args, ())
345 nt.assert_equal(args, ())
336 nt.assert_equal(kwargs, {
346 nt.assert_equal(kwargs, {
337 'data': {
347 'data': {
338 'text/plain': repr('x')
348 'text/plain': repr('x')
339 },
349 },
340 'metadata': {},
350 'metadata': {},
341 'transient': {
351 'transient': {
342 'display_id': '1',
352 'display_id': '1',
343 },
353 },
344 'update': True,
354 'update': True,
345 })
355 })
346 args, kwargs = pub.call_args_list[1]
356 args, kwargs = pub.call_args_list[1]
347 nt.assert_equal(args, ())
357 nt.assert_equal(args, ())
348 nt.assert_equal(kwargs, {
358 nt.assert_equal(kwargs, {
349 'data': {
359 'data': {
350 'text/plain': repr('y')
360 'text/plain': repr('y')
351 },
361 },
352 'metadata': {},
362 'metadata': {},
353 'transient': {
363 'transient': {
354 'display_id': '2',
364 'display_id': '2',
355 },
365 },
356 'update': True,
366 'update': True,
357 })
367 })
358
368
359
369
360 def test_display_handle():
370 def test_display_handle():
361 ip = get_ipython()
371 ip = get_ipython()
362 handle = display.DisplayHandle()
372 handle = display.DisplayHandle()
363 nt.assert_is_instance(handle.display_id, str)
373 nt.assert_is_instance(handle.display_id, str)
364 handle = display.DisplayHandle('my-id')
374 handle = display.DisplayHandle('my-id')
365 nt.assert_equal(handle.display_id, 'my-id')
375 nt.assert_equal(handle.display_id, 'my-id')
366 with mock.patch.object(ip.display_pub, 'publish') as pub:
376 with mock.patch.object(ip.display_pub, 'publish') as pub:
367 handle.display('x')
377 handle.display('x')
368 handle.update('y')
378 handle.update('y')
369
379
370 args, kwargs = pub.call_args_list[0]
380 args, kwargs = pub.call_args_list[0]
371 nt.assert_equal(args, ())
381 nt.assert_equal(args, ())
372 nt.assert_equal(kwargs, {
382 nt.assert_equal(kwargs, {
373 'data': {
383 'data': {
374 'text/plain': repr('x')
384 'text/plain': repr('x')
375 },
385 },
376 'metadata': {},
386 'metadata': {},
377 'transient': {
387 'transient': {
378 'display_id': handle.display_id,
388 'display_id': handle.display_id,
379 }
389 }
380 })
390 })
381 args, kwargs = pub.call_args_list[1]
391 args, kwargs = pub.call_args_list[1]
382 nt.assert_equal(args, ())
392 nt.assert_equal(args, ())
383 nt.assert_equal(kwargs, {
393 nt.assert_equal(kwargs, {
384 'data': {
394 'data': {
385 'text/plain': repr('y')
395 'text/plain': repr('y')
386 },
396 },
387 'metadata': {},
397 'metadata': {},
388 'transient': {
398 'transient': {
389 'display_id': handle.display_id,
399 'display_id': handle.display_id,
390 },
400 },
391 'update': True,
401 'update': True,
392 })
402 })
393
403
@@ -1,929 +1,930 b''
1 # -*- coding: utf-8 -*-
1 # -*- coding: utf-8 -*-
2 """Tests for the key interactiveshell module.
2 """Tests for the key interactiveshell module.
3
3
4 Historically the main classes in interactiveshell have been under-tested. This
4 Historically the main classes in interactiveshell have been under-tested. This
5 module should grow as many single-method tests as possible to trap many of the
5 module should grow as many single-method tests as possible to trap many of the
6 recurring bugs we seem to encounter with high-level interaction.
6 recurring bugs we seem to encounter with high-level interaction.
7 """
7 """
8
8
9 # Copyright (c) IPython Development Team.
9 # Copyright (c) IPython Development Team.
10 # Distributed under the terms of the Modified BSD License.
10 # Distributed under the terms of the Modified BSD License.
11
11
12 import ast
12 import ast
13 import os
13 import os
14 import signal
14 import signal
15 import shutil
15 import shutil
16 import sys
16 import sys
17 import tempfile
17 import tempfile
18 import unittest
18 import unittest
19 from unittest import mock
19 from unittest import mock
20
20
21 from os.path import join
21 from os.path import join
22
22
23 import nose.tools as nt
23 import nose.tools as nt
24
24
25 from IPython.core.error import InputRejected
25 from IPython.core.error import InputRejected
26 from IPython.core.inputtransformer import InputTransformer
26 from IPython.core.inputtransformer import InputTransformer
27 from IPython.testing.decorators import (
27 from IPython.testing.decorators import (
28 skipif, skip_win32, onlyif_unicode_paths, onlyif_cmds_exist,
28 skipif, skip_win32, onlyif_unicode_paths, onlyif_cmds_exist,
29 )
29 )
30 from IPython.testing import tools as tt
30 from IPython.testing import tools as tt
31 from IPython.utils.process import find_cmd
31 from IPython.utils.process import find_cmd
32
32
33 #-----------------------------------------------------------------------------
33 #-----------------------------------------------------------------------------
34 # Globals
34 # Globals
35 #-----------------------------------------------------------------------------
35 #-----------------------------------------------------------------------------
36 # This is used by every single test, no point repeating it ad nauseam
36 # This is used by every single test, no point repeating it ad nauseam
37 ip = get_ipython()
37 ip = get_ipython()
38
38
39 #-----------------------------------------------------------------------------
39 #-----------------------------------------------------------------------------
40 # Tests
40 # Tests
41 #-----------------------------------------------------------------------------
41 #-----------------------------------------------------------------------------
42
42
43 class DerivedInterrupt(KeyboardInterrupt):
43 class DerivedInterrupt(KeyboardInterrupt):
44 pass
44 pass
45
45
46 class InteractiveShellTestCase(unittest.TestCase):
46 class InteractiveShellTestCase(unittest.TestCase):
47 def test_naked_string_cells(self):
47 def test_naked_string_cells(self):
48 """Test that cells with only naked strings are fully executed"""
48 """Test that cells with only naked strings are fully executed"""
49 # First, single-line inputs
49 # First, single-line inputs
50 ip.run_cell('"a"\n')
50 ip.run_cell('"a"\n')
51 self.assertEqual(ip.user_ns['_'], 'a')
51 self.assertEqual(ip.user_ns['_'], 'a')
52 # And also multi-line cells
52 # And also multi-line cells
53 ip.run_cell('"""a\nb"""\n')
53 ip.run_cell('"""a\nb"""\n')
54 self.assertEqual(ip.user_ns['_'], 'a\nb')
54 self.assertEqual(ip.user_ns['_'], 'a\nb')
55
55
56 def test_run_empty_cell(self):
56 def test_run_empty_cell(self):
57 """Just make sure we don't get a horrible error with a blank
57 """Just make sure we don't get a horrible error with a blank
58 cell of input. Yes, I did overlook that."""
58 cell of input. Yes, I did overlook that."""
59 old_xc = ip.execution_count
59 old_xc = ip.execution_count
60 res = ip.run_cell('')
60 res = ip.run_cell('')
61 self.assertEqual(ip.execution_count, old_xc)
61 self.assertEqual(ip.execution_count, old_xc)
62 self.assertEqual(res.execution_count, None)
62 self.assertEqual(res.execution_count, None)
63
63
64 def test_run_cell_multiline(self):
64 def test_run_cell_multiline(self):
65 """Multi-block, multi-line cells must execute correctly.
65 """Multi-block, multi-line cells must execute correctly.
66 """
66 """
67 src = '\n'.join(["x=1",
67 src = '\n'.join(["x=1",
68 "y=2",
68 "y=2",
69 "if 1:",
69 "if 1:",
70 " x += 1",
70 " x += 1",
71 " y += 1",])
71 " y += 1",])
72 res = ip.run_cell(src)
72 res = ip.run_cell(src)
73 self.assertEqual(ip.user_ns['x'], 2)
73 self.assertEqual(ip.user_ns['x'], 2)
74 self.assertEqual(ip.user_ns['y'], 3)
74 self.assertEqual(ip.user_ns['y'], 3)
75 self.assertEqual(res.success, True)
75 self.assertEqual(res.success, True)
76 self.assertEqual(res.result, None)
76 self.assertEqual(res.result, None)
77
77
78 def test_multiline_string_cells(self):
78 def test_multiline_string_cells(self):
79 "Code sprinkled with multiline strings should execute (GH-306)"
79 "Code sprinkled with multiline strings should execute (GH-306)"
80 ip.run_cell('tmp=0')
80 ip.run_cell('tmp=0')
81 self.assertEqual(ip.user_ns['tmp'], 0)
81 self.assertEqual(ip.user_ns['tmp'], 0)
82 res = ip.run_cell('tmp=1;"""a\nb"""\n')
82 res = ip.run_cell('tmp=1;"""a\nb"""\n')
83 self.assertEqual(ip.user_ns['tmp'], 1)
83 self.assertEqual(ip.user_ns['tmp'], 1)
84 self.assertEqual(res.success, True)
84 self.assertEqual(res.success, True)
85 self.assertEqual(res.result, "a\nb")
85 self.assertEqual(res.result, "a\nb")
86
86
87 def test_dont_cache_with_semicolon(self):
87 def test_dont_cache_with_semicolon(self):
88 "Ending a line with semicolon should not cache the returned object (GH-307)"
88 "Ending a line with semicolon should not cache the returned object (GH-307)"
89 oldlen = len(ip.user_ns['Out'])
89 oldlen = len(ip.user_ns['Out'])
90 for cell in ['1;', '1;1;']:
90 for cell in ['1;', '1;1;']:
91 res = ip.run_cell(cell, store_history=True)
91 res = ip.run_cell(cell, store_history=True)
92 newlen = len(ip.user_ns['Out'])
92 newlen = len(ip.user_ns['Out'])
93 self.assertEqual(oldlen, newlen)
93 self.assertEqual(oldlen, newlen)
94 self.assertIsNone(res.result)
94 self.assertIsNone(res.result)
95 i = 0
95 i = 0
96 #also test the default caching behavior
96 #also test the default caching behavior
97 for cell in ['1', '1;1']:
97 for cell in ['1', '1;1']:
98 ip.run_cell(cell, store_history=True)
98 ip.run_cell(cell, store_history=True)
99 newlen = len(ip.user_ns['Out'])
99 newlen = len(ip.user_ns['Out'])
100 i += 1
100 i += 1
101 self.assertEqual(oldlen+i, newlen)
101 self.assertEqual(oldlen+i, newlen)
102
102
103 def test_syntax_error(self):
103 def test_syntax_error(self):
104 res = ip.run_cell("raise = 3")
104 res = ip.run_cell("raise = 3")
105 self.assertIsInstance(res.error_before_exec, SyntaxError)
105 self.assertIsInstance(res.error_before_exec, SyntaxError)
106
106
107 def test_In_variable(self):
107 def test_In_variable(self):
108 "Verify that In variable grows with user input (GH-284)"
108 "Verify that In variable grows with user input (GH-284)"
109 oldlen = len(ip.user_ns['In'])
109 oldlen = len(ip.user_ns['In'])
110 ip.run_cell('1;', store_history=True)
110 ip.run_cell('1;', store_history=True)
111 newlen = len(ip.user_ns['In'])
111 newlen = len(ip.user_ns['In'])
112 self.assertEqual(oldlen+1, newlen)
112 self.assertEqual(oldlen+1, newlen)
113 self.assertEqual(ip.user_ns['In'][-1],'1;')
113 self.assertEqual(ip.user_ns['In'][-1],'1;')
114
114
115 def test_magic_names_in_string(self):
115 def test_magic_names_in_string(self):
116 ip.run_cell('a = """\n%exit\n"""')
116 ip.run_cell('a = """\n%exit\n"""')
117 self.assertEqual(ip.user_ns['a'], '\n%exit\n')
117 self.assertEqual(ip.user_ns['a'], '\n%exit\n')
118
118
119 def test_trailing_newline(self):
119 def test_trailing_newline(self):
120 """test that running !(command) does not raise a SyntaxError"""
120 """test that running !(command) does not raise a SyntaxError"""
121 ip.run_cell('!(true)\n', False)
121 ip.run_cell('!(true)\n', False)
122 ip.run_cell('!(true)\n\n\n', False)
122 ip.run_cell('!(true)\n\n\n', False)
123
123
124 def test_gh_597(self):
124 def test_gh_597(self):
125 """Pretty-printing lists of objects with non-ascii reprs may cause
125 """Pretty-printing lists of objects with non-ascii reprs may cause
126 problems."""
126 problems."""
127 class Spam(object):
127 class Spam(object):
128 def __repr__(self):
128 def __repr__(self):
129 return "\xe9"*50
129 return "\xe9"*50
130 import IPython.core.formatters
130 import IPython.core.formatters
131 f = IPython.core.formatters.PlainTextFormatter()
131 f = IPython.core.formatters.PlainTextFormatter()
132 f([Spam(),Spam()])
132 f([Spam(),Spam()])
133
133
134
134
135 def test_future_flags(self):
135 def test_future_flags(self):
136 """Check that future flags are used for parsing code (gh-777)"""
136 """Check that future flags are used for parsing code (gh-777)"""
137 ip.run_cell('from __future__ import barry_as_FLUFL')
137 ip.run_cell('from __future__ import barry_as_FLUFL')
138 try:
138 try:
139 ip.run_cell('prfunc_return_val = 1 <> 2')
139 ip.run_cell('prfunc_return_val = 1 <> 2')
140 assert 'prfunc_return_val' in ip.user_ns
140 assert 'prfunc_return_val' in ip.user_ns
141 finally:
141 finally:
142 # Reset compiler flags so we don't mess up other tests.
142 # Reset compiler flags so we don't mess up other tests.
143 ip.compile.reset_compiler_flags()
143 ip.compile.reset_compiler_flags()
144
144
145 def test_can_pickle(self):
145 def test_can_pickle(self):
146 "Can we pickle objects defined interactively (GH-29)"
146 "Can we pickle objects defined interactively (GH-29)"
147 ip = get_ipython()
147 ip = get_ipython()
148 ip.reset()
148 ip.reset()
149 ip.run_cell(("class Mylist(list):\n"
149 ip.run_cell(("class Mylist(list):\n"
150 " def __init__(self,x=[]):\n"
150 " def __init__(self,x=[]):\n"
151 " list.__init__(self,x)"))
151 " list.__init__(self,x)"))
152 ip.run_cell("w=Mylist([1,2,3])")
152 ip.run_cell("w=Mylist([1,2,3])")
153
153
154 from pickle import dumps
154 from pickle import dumps
155
155
156 # We need to swap in our main module - this is only necessary
156 # We need to swap in our main module - this is only necessary
157 # inside the test framework, because IPython puts the interactive module
157 # inside the test framework, because IPython puts the interactive module
158 # in place (but the test framework undoes this).
158 # in place (but the test framework undoes this).
159 _main = sys.modules['__main__']
159 _main = sys.modules['__main__']
160 sys.modules['__main__'] = ip.user_module
160 sys.modules['__main__'] = ip.user_module
161 try:
161 try:
162 res = dumps(ip.user_ns["w"])
162 res = dumps(ip.user_ns["w"])
163 finally:
163 finally:
164 sys.modules['__main__'] = _main
164 sys.modules['__main__'] = _main
165 self.assertTrue(isinstance(res, bytes))
165 self.assertTrue(isinstance(res, bytes))
166
166
167 def test_global_ns(self):
167 def test_global_ns(self):
168 "Code in functions must be able to access variables outside them."
168 "Code in functions must be able to access variables outside them."
169 ip = get_ipython()
169 ip = get_ipython()
170 ip.run_cell("a = 10")
170 ip.run_cell("a = 10")
171 ip.run_cell(("def f(x):\n"
171 ip.run_cell(("def f(x):\n"
172 " return x + a"))
172 " return x + a"))
173 ip.run_cell("b = f(12)")
173 ip.run_cell("b = f(12)")
174 self.assertEqual(ip.user_ns["b"], 22)
174 self.assertEqual(ip.user_ns["b"], 22)
175
175
176 def test_bad_custom_tb(self):
176 def test_bad_custom_tb(self):
177 """Check that InteractiveShell is protected from bad custom exception handlers"""
177 """Check that InteractiveShell is protected from bad custom exception handlers"""
178 ip.set_custom_exc((IOError,), lambda etype,value,tb: 1/0)
178 ip.set_custom_exc((IOError,), lambda etype,value,tb: 1/0)
179 self.assertEqual(ip.custom_exceptions, (IOError,))
179 self.assertEqual(ip.custom_exceptions, (IOError,))
180 with tt.AssertPrints("Custom TB Handler failed", channel='stderr'):
180 with tt.AssertPrints("Custom TB Handler failed", channel='stderr'):
181 ip.run_cell(u'raise IOError("foo")')
181 ip.run_cell(u'raise IOError("foo")')
182 self.assertEqual(ip.custom_exceptions, ())
182 self.assertEqual(ip.custom_exceptions, ())
183
183
184 def test_bad_custom_tb_return(self):
184 def test_bad_custom_tb_return(self):
185 """Check that InteractiveShell is protected from bad return types in custom exception handlers"""
185 """Check that InteractiveShell is protected from bad return types in custom exception handlers"""
186 ip.set_custom_exc((NameError,),lambda etype,value,tb, tb_offset=None: 1)
186 ip.set_custom_exc((NameError,),lambda etype,value,tb, tb_offset=None: 1)
187 self.assertEqual(ip.custom_exceptions, (NameError,))
187 self.assertEqual(ip.custom_exceptions, (NameError,))
188 with tt.AssertPrints("Custom TB Handler failed", channel='stderr'):
188 with tt.AssertPrints("Custom TB Handler failed", channel='stderr'):
189 ip.run_cell(u'a=abracadabra')
189 ip.run_cell(u'a=abracadabra')
190 self.assertEqual(ip.custom_exceptions, ())
190 self.assertEqual(ip.custom_exceptions, ())
191
191
192 def test_drop_by_id(self):
192 def test_drop_by_id(self):
193 myvars = {"a":object(), "b":object(), "c": object()}
193 myvars = {"a":object(), "b":object(), "c": object()}
194 ip.push(myvars, interactive=False)
194 ip.push(myvars, interactive=False)
195 for name in myvars:
195 for name in myvars:
196 assert name in ip.user_ns, name
196 assert name in ip.user_ns, name
197 assert name in ip.user_ns_hidden, name
197 assert name in ip.user_ns_hidden, name
198 ip.user_ns['b'] = 12
198 ip.user_ns['b'] = 12
199 ip.drop_by_id(myvars)
199 ip.drop_by_id(myvars)
200 for name in ["a", "c"]:
200 for name in ["a", "c"]:
201 assert name not in ip.user_ns, name
201 assert name not in ip.user_ns, name
202 assert name not in ip.user_ns_hidden, name
202 assert name not in ip.user_ns_hidden, name
203 assert ip.user_ns['b'] == 12
203 assert ip.user_ns['b'] == 12
204 ip.reset()
204 ip.reset()
205
205
206 def test_var_expand(self):
206 def test_var_expand(self):
207 ip.user_ns['f'] = u'Ca\xf1o'
207 ip.user_ns['f'] = u'Ca\xf1o'
208 self.assertEqual(ip.var_expand(u'echo $f'), u'echo Ca\xf1o')
208 self.assertEqual(ip.var_expand(u'echo $f'), u'echo Ca\xf1o')
209 self.assertEqual(ip.var_expand(u'echo {f}'), u'echo Ca\xf1o')
209 self.assertEqual(ip.var_expand(u'echo {f}'), u'echo Ca\xf1o')
210 self.assertEqual(ip.var_expand(u'echo {f[:-1]}'), u'echo Ca\xf1')
210 self.assertEqual(ip.var_expand(u'echo {f[:-1]}'), u'echo Ca\xf1')
211 self.assertEqual(ip.var_expand(u'echo {1*2}'), u'echo 2')
211 self.assertEqual(ip.var_expand(u'echo {1*2}'), u'echo 2')
212
212
213 self.assertEqual(ip.var_expand(u"grep x | awk '{print $1}'"), u"grep x | awk '{print $1}'")
213 self.assertEqual(ip.var_expand(u"grep x | awk '{print $1}'"), u"grep x | awk '{print $1}'")
214
214
215 ip.user_ns['f'] = b'Ca\xc3\xb1o'
215 ip.user_ns['f'] = b'Ca\xc3\xb1o'
216 # This should not raise any exception:
216 # This should not raise any exception:
217 ip.var_expand(u'echo $f')
217 ip.var_expand(u'echo $f')
218
218
219 def test_var_expand_local(self):
219 def test_var_expand_local(self):
220 """Test local variable expansion in !system and %magic calls"""
220 """Test local variable expansion in !system and %magic calls"""
221 # !system
221 # !system
222 ip.run_cell('def test():\n'
222 ip.run_cell('def test():\n'
223 ' lvar = "ttt"\n'
223 ' lvar = "ttt"\n'
224 ' ret = !echo {lvar}\n'
224 ' ret = !echo {lvar}\n'
225 ' return ret[0]\n')
225 ' return ret[0]\n')
226 res = ip.user_ns['test']()
226 res = ip.user_ns['test']()
227 nt.assert_in('ttt', res)
227 nt.assert_in('ttt', res)
228
228
229 # %magic
229 # %magic
230 ip.run_cell('def makemacro():\n'
230 ip.run_cell('def makemacro():\n'
231 ' macroname = "macro_var_expand_locals"\n'
231 ' macroname = "macro_var_expand_locals"\n'
232 ' %macro {macroname} codestr\n')
232 ' %macro {macroname} codestr\n')
233 ip.user_ns['codestr'] = "str(12)"
233 ip.user_ns['codestr'] = "str(12)"
234 ip.run_cell('makemacro()')
234 ip.run_cell('makemacro()')
235 nt.assert_in('macro_var_expand_locals', ip.user_ns)
235 nt.assert_in('macro_var_expand_locals', ip.user_ns)
236
236
237 def test_var_expand_self(self):
237 def test_var_expand_self(self):
238 """Test variable expansion with the name 'self', which was failing.
238 """Test variable expansion with the name 'self', which was failing.
239
239
240 See https://github.com/ipython/ipython/issues/1878#issuecomment-7698218
240 See https://github.com/ipython/ipython/issues/1878#issuecomment-7698218
241 """
241 """
242 ip.run_cell('class cTest:\n'
242 ip.run_cell('class cTest:\n'
243 ' classvar="see me"\n'
243 ' classvar="see me"\n'
244 ' def test(self):\n'
244 ' def test(self):\n'
245 ' res = !echo Variable: {self.classvar}\n'
245 ' res = !echo Variable: {self.classvar}\n'
246 ' return res[0]\n')
246 ' return res[0]\n')
247 nt.assert_in('see me', ip.user_ns['cTest']().test())
247 nt.assert_in('see me', ip.user_ns['cTest']().test())
248
248
249 def test_bad_var_expand(self):
249 def test_bad_var_expand(self):
250 """var_expand on invalid formats shouldn't raise"""
250 """var_expand on invalid formats shouldn't raise"""
251 # SyntaxError
251 # SyntaxError
252 self.assertEqual(ip.var_expand(u"{'a':5}"), u"{'a':5}")
252 self.assertEqual(ip.var_expand(u"{'a':5}"), u"{'a':5}")
253 # NameError
253 # NameError
254 self.assertEqual(ip.var_expand(u"{asdf}"), u"{asdf}")
254 self.assertEqual(ip.var_expand(u"{asdf}"), u"{asdf}")
255 # ZeroDivisionError
255 # ZeroDivisionError
256 self.assertEqual(ip.var_expand(u"{1/0}"), u"{1/0}")
256 self.assertEqual(ip.var_expand(u"{1/0}"), u"{1/0}")
257
257
258 def test_silent_postexec(self):
258 def test_silent_postexec(self):
259 """run_cell(silent=True) doesn't invoke pre/post_run_cell callbacks"""
259 """run_cell(silent=True) doesn't invoke pre/post_run_cell callbacks"""
260 pre_explicit = mock.Mock()
260 pre_explicit = mock.Mock()
261 pre_always = mock.Mock()
261 pre_always = mock.Mock()
262 post_explicit = mock.Mock()
262 post_explicit = mock.Mock()
263 post_always = mock.Mock()
263 post_always = mock.Mock()
264 all_mocks = [pre_explicit, pre_always, post_explicit, post_always]
264 all_mocks = [pre_explicit, pre_always, post_explicit, post_always]
265
265
266 ip.events.register('pre_run_cell', pre_explicit)
266 ip.events.register('pre_run_cell', pre_explicit)
267 ip.events.register('pre_execute', pre_always)
267 ip.events.register('pre_execute', pre_always)
268 ip.events.register('post_run_cell', post_explicit)
268 ip.events.register('post_run_cell', post_explicit)
269 ip.events.register('post_execute', post_always)
269 ip.events.register('post_execute', post_always)
270
270
271 try:
271 try:
272 ip.run_cell("1", silent=True)
272 ip.run_cell("1", silent=True)
273 assert pre_always.called
273 assert pre_always.called
274 assert not pre_explicit.called
274 assert not pre_explicit.called
275 assert post_always.called
275 assert post_always.called
276 assert not post_explicit.called
276 assert not post_explicit.called
277 # double-check that non-silent exec did what we expected
277 # double-check that non-silent exec did what we expected
278 # silent to avoid
278 # silent to avoid
279 ip.run_cell("1")
279 ip.run_cell("1")
280 assert pre_explicit.called
280 assert pre_explicit.called
281 assert post_explicit.called
281 assert post_explicit.called
282 info, = pre_explicit.call_args[0]
282 info, = pre_explicit.call_args[0]
283 result, = post_explicit.call_args[0]
283 result, = post_explicit.call_args[0]
284 self.assertEqual(info, result.info)
284 self.assertEqual(info, result.info)
285 # check that post hooks are always called
285 # check that post hooks are always called
286 [m.reset_mock() for m in all_mocks]
286 [m.reset_mock() for m in all_mocks]
287 ip.run_cell("syntax error")
287 ip.run_cell("syntax error")
288 assert pre_always.called
288 assert pre_always.called
289 assert pre_explicit.called
289 assert pre_explicit.called
290 assert post_always.called
290 assert post_always.called
291 assert post_explicit.called
291 assert post_explicit.called
292 info, = pre_explicit.call_args[0]
292 info, = pre_explicit.call_args[0]
293 result, = post_explicit.call_args[0]
293 result, = post_explicit.call_args[0]
294 self.assertEqual(info, result.info)
294 self.assertEqual(info, result.info)
295 finally:
295 finally:
296 # remove post-exec
296 # remove post-exec
297 ip.events.unregister('pre_run_cell', pre_explicit)
297 ip.events.unregister('pre_run_cell', pre_explicit)
298 ip.events.unregister('pre_execute', pre_always)
298 ip.events.unregister('pre_execute', pre_always)
299 ip.events.unregister('post_run_cell', post_explicit)
299 ip.events.unregister('post_run_cell', post_explicit)
300 ip.events.unregister('post_execute', post_always)
300 ip.events.unregister('post_execute', post_always)
301
301
302 def test_silent_noadvance(self):
302 def test_silent_noadvance(self):
303 """run_cell(silent=True) doesn't advance execution_count"""
303 """run_cell(silent=True) doesn't advance execution_count"""
304 ec = ip.execution_count
304 ec = ip.execution_count
305 # silent should force store_history=False
305 # silent should force store_history=False
306 ip.run_cell("1", store_history=True, silent=True)
306 ip.run_cell("1", store_history=True, silent=True)
307
307
308 self.assertEqual(ec, ip.execution_count)
308 self.assertEqual(ec, ip.execution_count)
309 # double-check that non-silent exec did what we expected
309 # double-check that non-silent exec did what we expected
310 # silent to avoid
310 # silent to avoid
311 ip.run_cell("1", store_history=True)
311 ip.run_cell("1", store_history=True)
312 self.assertEqual(ec+1, ip.execution_count)
312 self.assertEqual(ec+1, ip.execution_count)
313
313
314 def test_silent_nodisplayhook(self):
314 def test_silent_nodisplayhook(self):
315 """run_cell(silent=True) doesn't trigger displayhook"""
315 """run_cell(silent=True) doesn't trigger displayhook"""
316 d = dict(called=False)
316 d = dict(called=False)
317
317
318 trap = ip.display_trap
318 trap = ip.display_trap
319 save_hook = trap.hook
319 save_hook = trap.hook
320
320
321 def failing_hook(*args, **kwargs):
321 def failing_hook(*args, **kwargs):
322 d['called'] = True
322 d['called'] = True
323
323
324 try:
324 try:
325 trap.hook = failing_hook
325 trap.hook = failing_hook
326 res = ip.run_cell("1", silent=True)
326 res = ip.run_cell("1", silent=True)
327 self.assertFalse(d['called'])
327 self.assertFalse(d['called'])
328 self.assertIsNone(res.result)
328 self.assertIsNone(res.result)
329 # double-check that non-silent exec did what we expected
329 # double-check that non-silent exec did what we expected
330 # silent to avoid
330 # silent to avoid
331 ip.run_cell("1")
331 ip.run_cell("1")
332 self.assertTrue(d['called'])
332 self.assertTrue(d['called'])
333 finally:
333 finally:
334 trap.hook = save_hook
334 trap.hook = save_hook
335
335
336 def test_ofind_line_magic(self):
336 def test_ofind_line_magic(self):
337 from IPython.core.magic import register_line_magic
337 from IPython.core.magic import register_line_magic
338
338
339 @register_line_magic
339 @register_line_magic
340 def lmagic(line):
340 def lmagic(line):
341 "A line magic"
341 "A line magic"
342
342
343 # Get info on line magic
343 # Get info on line magic
344 lfind = ip._ofind('lmagic')
344 lfind = ip._ofind('lmagic')
345 info = dict(found=True, isalias=False, ismagic=True,
345 info = dict(found=True, isalias=False, ismagic=True,
346 namespace = 'IPython internal', obj= lmagic.__wrapped__,
346 namespace = 'IPython internal', obj= lmagic.__wrapped__,
347 parent = None)
347 parent = None)
348 nt.assert_equal(lfind, info)
348 nt.assert_equal(lfind, info)
349
349
350 def test_ofind_cell_magic(self):
350 def test_ofind_cell_magic(self):
351 from IPython.core.magic import register_cell_magic
351 from IPython.core.magic import register_cell_magic
352
352
353 @register_cell_magic
353 @register_cell_magic
354 def cmagic(line, cell):
354 def cmagic(line, cell):
355 "A cell magic"
355 "A cell magic"
356
356
357 # Get info on cell magic
357 # Get info on cell magic
358 find = ip._ofind('cmagic')
358 find = ip._ofind('cmagic')
359 info = dict(found=True, isalias=False, ismagic=True,
359 info = dict(found=True, isalias=False, ismagic=True,
360 namespace = 'IPython internal', obj= cmagic.__wrapped__,
360 namespace = 'IPython internal', obj= cmagic.__wrapped__,
361 parent = None)
361 parent = None)
362 nt.assert_equal(find, info)
362 nt.assert_equal(find, info)
363
363
364 def test_ofind_property_with_error(self):
364 def test_ofind_property_with_error(self):
365 class A(object):
365 class A(object):
366 @property
366 @property
367 def foo(self):
367 def foo(self):
368 raise NotImplementedError()
368 raise NotImplementedError()
369 a = A()
369 a = A()
370
370
371 found = ip._ofind('a.foo', [('locals', locals())])
371 found = ip._ofind('a.foo', [('locals', locals())])
372 info = dict(found=True, isalias=False, ismagic=False,
372 info = dict(found=True, isalias=False, ismagic=False,
373 namespace='locals', obj=A.foo, parent=a)
373 namespace='locals', obj=A.foo, parent=a)
374 nt.assert_equal(found, info)
374 nt.assert_equal(found, info)
375
375
376 def test_ofind_multiple_attribute_lookups(self):
376 def test_ofind_multiple_attribute_lookups(self):
377 class A(object):
377 class A(object):
378 @property
378 @property
379 def foo(self):
379 def foo(self):
380 raise NotImplementedError()
380 raise NotImplementedError()
381
381
382 a = A()
382 a = A()
383 a.a = A()
383 a.a = A()
384 a.a.a = A()
384 a.a.a = A()
385
385
386 found = ip._ofind('a.a.a.foo', [('locals', locals())])
386 found = ip._ofind('a.a.a.foo', [('locals', locals())])
387 info = dict(found=True, isalias=False, ismagic=False,
387 info = dict(found=True, isalias=False, ismagic=False,
388 namespace='locals', obj=A.foo, parent=a.a.a)
388 namespace='locals', obj=A.foo, parent=a.a.a)
389 nt.assert_equal(found, info)
389 nt.assert_equal(found, info)
390
390
391 def test_ofind_slotted_attributes(self):
391 def test_ofind_slotted_attributes(self):
392 class A(object):
392 class A(object):
393 __slots__ = ['foo']
393 __slots__ = ['foo']
394 def __init__(self):
394 def __init__(self):
395 self.foo = 'bar'
395 self.foo = 'bar'
396
396
397 a = A()
397 a = A()
398 found = ip._ofind('a.foo', [('locals', locals())])
398 found = ip._ofind('a.foo', [('locals', locals())])
399 info = dict(found=True, isalias=False, ismagic=False,
399 info = dict(found=True, isalias=False, ismagic=False,
400 namespace='locals', obj=a.foo, parent=a)
400 namespace='locals', obj=a.foo, parent=a)
401 nt.assert_equal(found, info)
401 nt.assert_equal(found, info)
402
402
403 found = ip._ofind('a.bar', [('locals', locals())])
403 found = ip._ofind('a.bar', [('locals', locals())])
404 info = dict(found=False, isalias=False, ismagic=False,
404 info = dict(found=False, isalias=False, ismagic=False,
405 namespace=None, obj=None, parent=a)
405 namespace=None, obj=None, parent=a)
406 nt.assert_equal(found, info)
406 nt.assert_equal(found, info)
407
407
408 def test_ofind_prefers_property_to_instance_level_attribute(self):
408 def test_ofind_prefers_property_to_instance_level_attribute(self):
409 class A(object):
409 class A(object):
410 @property
410 @property
411 def foo(self):
411 def foo(self):
412 return 'bar'
412 return 'bar'
413 a = A()
413 a = A()
414 a.__dict__['foo'] = 'baz'
414 a.__dict__['foo'] = 'baz'
415 nt.assert_equal(a.foo, 'bar')
415 nt.assert_equal(a.foo, 'bar')
416 found = ip._ofind('a.foo', [('locals', locals())])
416 found = ip._ofind('a.foo', [('locals', locals())])
417 nt.assert_is(found['obj'], A.foo)
417 nt.assert_is(found['obj'], A.foo)
418
418
419 def test_custom_syntaxerror_exception(self):
419 def test_custom_syntaxerror_exception(self):
420 called = []
420 called = []
421 def my_handler(shell, etype, value, tb, tb_offset=None):
421 def my_handler(shell, etype, value, tb, tb_offset=None):
422 called.append(etype)
422 called.append(etype)
423 shell.showtraceback((etype, value, tb), tb_offset=tb_offset)
423 shell.showtraceback((etype, value, tb), tb_offset=tb_offset)
424
424
425 ip.set_custom_exc((SyntaxError,), my_handler)
425 ip.set_custom_exc((SyntaxError,), my_handler)
426 try:
426 try:
427 ip.run_cell("1f")
427 ip.run_cell("1f")
428 # Check that this was called, and only once.
428 # Check that this was called, and only once.
429 self.assertEqual(called, [SyntaxError])
429 self.assertEqual(called, [SyntaxError])
430 finally:
430 finally:
431 # Reset the custom exception hook
431 # Reset the custom exception hook
432 ip.set_custom_exc((), None)
432 ip.set_custom_exc((), None)
433
433
434 def test_custom_exception(self):
434 def test_custom_exception(self):
435 called = []
435 called = []
436 def my_handler(shell, etype, value, tb, tb_offset=None):
436 def my_handler(shell, etype, value, tb, tb_offset=None):
437 called.append(etype)
437 called.append(etype)
438 shell.showtraceback((etype, value, tb), tb_offset=tb_offset)
438 shell.showtraceback((etype, value, tb), tb_offset=tb_offset)
439
439
440 ip.set_custom_exc((ValueError,), my_handler)
440 ip.set_custom_exc((ValueError,), my_handler)
441 try:
441 try:
442 res = ip.run_cell("raise ValueError('test')")
442 res = ip.run_cell("raise ValueError('test')")
443 # Check that this was called, and only once.
443 # Check that this was called, and only once.
444 self.assertEqual(called, [ValueError])
444 self.assertEqual(called, [ValueError])
445 # Check that the error is on the result object
445 # Check that the error is on the result object
446 self.assertIsInstance(res.error_in_exec, ValueError)
446 self.assertIsInstance(res.error_in_exec, ValueError)
447 finally:
447 finally:
448 # Reset the custom exception hook
448 # Reset the custom exception hook
449 ip.set_custom_exc((), None)
449 ip.set_custom_exc((), None)
450
450
451 def test_mktempfile(self):
451 def test_mktempfile(self):
452 filename = ip.mktempfile()
452 filename = ip.mktempfile()
453 # Check that we can open the file again on Windows
453 # Check that we can open the file again on Windows
454 with open(filename, 'w') as f:
454 with open(filename, 'w') as f:
455 f.write('abc')
455 f.write('abc')
456
456
457 filename = ip.mktempfile(data='blah')
457 filename = ip.mktempfile(data='blah')
458 with open(filename, 'r') as f:
458 with open(filename, 'r') as f:
459 self.assertEqual(f.read(), 'blah')
459 self.assertEqual(f.read(), 'blah')
460
460
461 def test_new_main_mod(self):
461 def test_new_main_mod(self):
462 # Smoketest to check that this accepts a unicode module name
462 # Smoketest to check that this accepts a unicode module name
463 name = u'jiefmw'
463 name = u'jiefmw'
464 mod = ip.new_main_mod(u'%s.py' % name, name)
464 mod = ip.new_main_mod(u'%s.py' % name, name)
465 self.assertEqual(mod.__name__, name)
465 self.assertEqual(mod.__name__, name)
466
466
467 def test_get_exception_only(self):
467 def test_get_exception_only(self):
468 try:
468 try:
469 raise KeyboardInterrupt
469 raise KeyboardInterrupt
470 except KeyboardInterrupt:
470 except KeyboardInterrupt:
471 msg = ip.get_exception_only()
471 msg = ip.get_exception_only()
472 self.assertEqual(msg, 'KeyboardInterrupt\n')
472 self.assertEqual(msg, 'KeyboardInterrupt\n')
473
473
474 try:
474 try:
475 raise DerivedInterrupt("foo")
475 raise DerivedInterrupt("foo")
476 except KeyboardInterrupt:
476 except KeyboardInterrupt:
477 msg = ip.get_exception_only()
477 msg = ip.get_exception_only()
478 self.assertEqual(msg, 'IPython.core.tests.test_interactiveshell.DerivedInterrupt: foo\n')
478 self.assertEqual(msg, 'IPython.core.tests.test_interactiveshell.DerivedInterrupt: foo\n')
479
479
480 def test_inspect_text(self):
480 def test_inspect_text(self):
481 ip.run_cell('a = 5')
481 ip.run_cell('a = 5')
482 text = ip.object_inspect_text('a')
482 text = ip.object_inspect_text('a')
483 self.assertIsInstance(text, str)
483 self.assertIsInstance(text, str)
484
484
485 def test_last_execution_result(self):
485 def test_last_execution_result(self):
486 """ Check that last execution result gets set correctly (GH-10702) """
486 """ Check that last execution result gets set correctly (GH-10702) """
487 result = ip.run_cell('a = 5; a')
487 result = ip.run_cell('a = 5; a')
488 self.assertTrue(ip.last_execution_succeeded)
488 self.assertTrue(ip.last_execution_succeeded)
489 self.assertEqual(ip.last_execution_result.result, 5)
489 self.assertEqual(ip.last_execution_result.result, 5)
490
490
491 result = ip.run_cell('a = x_invalid_id_x')
491 result = ip.run_cell('a = x_invalid_id_x')
492 self.assertFalse(ip.last_execution_succeeded)
492 self.assertFalse(ip.last_execution_succeeded)
493 self.assertFalse(ip.last_execution_result.success)
493 self.assertFalse(ip.last_execution_result.success)
494 self.assertIsInstance(ip.last_execution_result.error_in_exec, NameError)
494 self.assertIsInstance(ip.last_execution_result.error_in_exec, NameError)
495
495
496
496
497 class TestSafeExecfileNonAsciiPath(unittest.TestCase):
497 class TestSafeExecfileNonAsciiPath(unittest.TestCase):
498
498
499 @onlyif_unicode_paths
499 @onlyif_unicode_paths
500 def setUp(self):
500 def setUp(self):
501 self.BASETESTDIR = tempfile.mkdtemp()
501 self.BASETESTDIR = tempfile.mkdtemp()
502 self.TESTDIR = join(self.BASETESTDIR, u"åäö")
502 self.TESTDIR = join(self.BASETESTDIR, u"åäö")
503 os.mkdir(self.TESTDIR)
503 os.mkdir(self.TESTDIR)
504 with open(join(self.TESTDIR, u"åäötestscript.py"), "w") as sfile:
504 with open(join(self.TESTDIR, u"åäötestscript.py"), "w") as sfile:
505 sfile.write("pass\n")
505 sfile.write("pass\n")
506 self.oldpath = os.getcwd()
506 self.oldpath = os.getcwd()
507 os.chdir(self.TESTDIR)
507 os.chdir(self.TESTDIR)
508 self.fname = u"åäötestscript.py"
508 self.fname = u"åäötestscript.py"
509
509
510 def tearDown(self):
510 def tearDown(self):
511 os.chdir(self.oldpath)
511 os.chdir(self.oldpath)
512 shutil.rmtree(self.BASETESTDIR)
512 shutil.rmtree(self.BASETESTDIR)
513
513
514 @onlyif_unicode_paths
514 @onlyif_unicode_paths
515 def test_1(self):
515 def test_1(self):
516 """Test safe_execfile with non-ascii path
516 """Test safe_execfile with non-ascii path
517 """
517 """
518 ip.safe_execfile(self.fname, {}, raise_exceptions=True)
518 ip.safe_execfile(self.fname, {}, raise_exceptions=True)
519
519
520 class ExitCodeChecks(tt.TempFileMixin):
520 class ExitCodeChecks(tt.TempFileMixin):
521 def test_exit_code_ok(self):
521 def test_exit_code_ok(self):
522 self.system('exit 0')
522 self.system('exit 0')
523 self.assertEqual(ip.user_ns['_exit_code'], 0)
523 self.assertEqual(ip.user_ns['_exit_code'], 0)
524
524
525 def test_exit_code_error(self):
525 def test_exit_code_error(self):
526 self.system('exit 1')
526 self.system('exit 1')
527 self.assertEqual(ip.user_ns['_exit_code'], 1)
527 self.assertEqual(ip.user_ns['_exit_code'], 1)
528
528
529 @skipif(not hasattr(signal, 'SIGALRM'))
529 @skipif(not hasattr(signal, 'SIGALRM'))
530 def test_exit_code_signal(self):
530 def test_exit_code_signal(self):
531 self.mktmp("import signal, time\n"
531 self.mktmp("import signal, time\n"
532 "signal.setitimer(signal.ITIMER_REAL, 0.1)\n"
532 "signal.setitimer(signal.ITIMER_REAL, 0.1)\n"
533 "time.sleep(1)\n")
533 "time.sleep(1)\n")
534 self.system("%s %s" % (sys.executable, self.fname))
534 self.system("%s %s" % (sys.executable, self.fname))
535 self.assertEqual(ip.user_ns['_exit_code'], -signal.SIGALRM)
535 self.assertEqual(ip.user_ns['_exit_code'], -signal.SIGALRM)
536
536
537 @onlyif_cmds_exist("csh")
537 @onlyif_cmds_exist("csh")
538 def test_exit_code_signal_csh(self):
538 def test_exit_code_signal_csh(self):
539 SHELL = os.environ.get('SHELL', None)
539 SHELL = os.environ.get('SHELL', None)
540 os.environ['SHELL'] = find_cmd("csh")
540 os.environ['SHELL'] = find_cmd("csh")
541 try:
541 try:
542 self.test_exit_code_signal()
542 self.test_exit_code_signal()
543 finally:
543 finally:
544 if SHELL is not None:
544 if SHELL is not None:
545 os.environ['SHELL'] = SHELL
545 os.environ['SHELL'] = SHELL
546 else:
546 else:
547 del os.environ['SHELL']
547 del os.environ['SHELL']
548
548
549 class TestSystemRaw(unittest.TestCase, ExitCodeChecks):
549
550 class TestSystemRaw(ExitCodeChecks, unittest.TestCase):
550 system = ip.system_raw
551 system = ip.system_raw
551
552
552 @onlyif_unicode_paths
553 @onlyif_unicode_paths
553 def test_1(self):
554 def test_1(self):
554 """Test system_raw with non-ascii cmd
555 """Test system_raw with non-ascii cmd
555 """
556 """
556 cmd = u'''python -c "'åäö'" '''
557 cmd = u'''python -c "'åäö'" '''
557 ip.system_raw(cmd)
558 ip.system_raw(cmd)
558
559
559 @mock.patch('subprocess.call', side_effect=KeyboardInterrupt)
560 @mock.patch('subprocess.call', side_effect=KeyboardInterrupt)
560 @mock.patch('os.system', side_effect=KeyboardInterrupt)
561 @mock.patch('os.system', side_effect=KeyboardInterrupt)
561 def test_control_c(self, *mocks):
562 def test_control_c(self, *mocks):
562 try:
563 try:
563 self.system("sleep 1 # wont happen")
564 self.system("sleep 1 # wont happen")
564 except KeyboardInterrupt:
565 except KeyboardInterrupt:
565 self.fail("system call should intercept "
566 self.fail("system call should intercept "
566 "keyboard interrupt from subprocess.call")
567 "keyboard interrupt from subprocess.call")
567 self.assertEqual(ip.user_ns['_exit_code'], -signal.SIGINT)
568 self.assertEqual(ip.user_ns['_exit_code'], -signal.SIGINT)
568
569
569 # TODO: Exit codes are currently ignored on Windows.
570 # TODO: Exit codes are currently ignored on Windows.
570 class TestSystemPipedExitCode(unittest.TestCase, ExitCodeChecks):
571 class TestSystemPipedExitCode(ExitCodeChecks, unittest.TestCase):
571 system = ip.system_piped
572 system = ip.system_piped
572
573
573 @skip_win32
574 @skip_win32
574 def test_exit_code_ok(self):
575 def test_exit_code_ok(self):
575 ExitCodeChecks.test_exit_code_ok(self)
576 ExitCodeChecks.test_exit_code_ok(self)
576
577
577 @skip_win32
578 @skip_win32
578 def test_exit_code_error(self):
579 def test_exit_code_error(self):
579 ExitCodeChecks.test_exit_code_error(self)
580 ExitCodeChecks.test_exit_code_error(self)
580
581
581 @skip_win32
582 @skip_win32
582 def test_exit_code_signal(self):
583 def test_exit_code_signal(self):
583 ExitCodeChecks.test_exit_code_signal(self)
584 ExitCodeChecks.test_exit_code_signal(self)
584
585
585 class TestModules(unittest.TestCase, tt.TempFileMixin):
586 class TestModules(tt.TempFileMixin, unittest.TestCase):
586 def test_extraneous_loads(self):
587 def test_extraneous_loads(self):
587 """Test we're not loading modules on startup that we shouldn't.
588 """Test we're not loading modules on startup that we shouldn't.
588 """
589 """
589 self.mktmp("import sys\n"
590 self.mktmp("import sys\n"
590 "print('numpy' in sys.modules)\n"
591 "print('numpy' in sys.modules)\n"
591 "print('ipyparallel' in sys.modules)\n"
592 "print('ipyparallel' in sys.modules)\n"
592 "print('ipykernel' in sys.modules)\n"
593 "print('ipykernel' in sys.modules)\n"
593 )
594 )
594 out = "False\nFalse\nFalse\n"
595 out = "False\nFalse\nFalse\n"
595 tt.ipexec_validate(self.fname, out)
596 tt.ipexec_validate(self.fname, out)
596
597
597 class Negator(ast.NodeTransformer):
598 class Negator(ast.NodeTransformer):
598 """Negates all number literals in an AST."""
599 """Negates all number literals in an AST."""
599 def visit_Num(self, node):
600 def visit_Num(self, node):
600 node.n = -node.n
601 node.n = -node.n
601 return node
602 return node
602
603
603 class TestAstTransform(unittest.TestCase):
604 class TestAstTransform(unittest.TestCase):
604 def setUp(self):
605 def setUp(self):
605 self.negator = Negator()
606 self.negator = Negator()
606 ip.ast_transformers.append(self.negator)
607 ip.ast_transformers.append(self.negator)
607
608
608 def tearDown(self):
609 def tearDown(self):
609 ip.ast_transformers.remove(self.negator)
610 ip.ast_transformers.remove(self.negator)
610
611
611 def test_run_cell(self):
612 def test_run_cell(self):
612 with tt.AssertPrints('-34'):
613 with tt.AssertPrints('-34'):
613 ip.run_cell('print (12 + 22)')
614 ip.run_cell('print (12 + 22)')
614
615
615 # A named reference to a number shouldn't be transformed.
616 # A named reference to a number shouldn't be transformed.
616 ip.user_ns['n'] = 55
617 ip.user_ns['n'] = 55
617 with tt.AssertNotPrints('-55'):
618 with tt.AssertNotPrints('-55'):
618 ip.run_cell('print (n)')
619 ip.run_cell('print (n)')
619
620
620 def test_timeit(self):
621 def test_timeit(self):
621 called = set()
622 called = set()
622 def f(x):
623 def f(x):
623 called.add(x)
624 called.add(x)
624 ip.push({'f':f})
625 ip.push({'f':f})
625
626
626 with tt.AssertPrints("std. dev. of"):
627 with tt.AssertPrints("std. dev. of"):
627 ip.run_line_magic("timeit", "-n1 f(1)")
628 ip.run_line_magic("timeit", "-n1 f(1)")
628 self.assertEqual(called, {-1})
629 self.assertEqual(called, {-1})
629 called.clear()
630 called.clear()
630
631
631 with tt.AssertPrints("std. dev. of"):
632 with tt.AssertPrints("std. dev. of"):
632 ip.run_cell_magic("timeit", "-n1 f(2)", "f(3)")
633 ip.run_cell_magic("timeit", "-n1 f(2)", "f(3)")
633 self.assertEqual(called, {-2, -3})
634 self.assertEqual(called, {-2, -3})
634
635
635 def test_time(self):
636 def test_time(self):
636 called = []
637 called = []
637 def f(x):
638 def f(x):
638 called.append(x)
639 called.append(x)
639 ip.push({'f':f})
640 ip.push({'f':f})
640
641
641 # Test with an expression
642 # Test with an expression
642 with tt.AssertPrints("Wall time: "):
643 with tt.AssertPrints("Wall time: "):
643 ip.run_line_magic("time", "f(5+9)")
644 ip.run_line_magic("time", "f(5+9)")
644 self.assertEqual(called, [-14])
645 self.assertEqual(called, [-14])
645 called[:] = []
646 called[:] = []
646
647
647 # Test with a statement (different code path)
648 # Test with a statement (different code path)
648 with tt.AssertPrints("Wall time: "):
649 with tt.AssertPrints("Wall time: "):
649 ip.run_line_magic("time", "a = f(-3 + -2)")
650 ip.run_line_magic("time", "a = f(-3 + -2)")
650 self.assertEqual(called, [5])
651 self.assertEqual(called, [5])
651
652
652 def test_macro(self):
653 def test_macro(self):
653 ip.push({'a':10})
654 ip.push({'a':10})
654 # The AST transformation makes this do a+=-1
655 # The AST transformation makes this do a+=-1
655 ip.define_macro("amacro", "a+=1\nprint(a)")
656 ip.define_macro("amacro", "a+=1\nprint(a)")
656
657
657 with tt.AssertPrints("9"):
658 with tt.AssertPrints("9"):
658 ip.run_cell("amacro")
659 ip.run_cell("amacro")
659 with tt.AssertPrints("8"):
660 with tt.AssertPrints("8"):
660 ip.run_cell("amacro")
661 ip.run_cell("amacro")
661
662
662 class IntegerWrapper(ast.NodeTransformer):
663 class IntegerWrapper(ast.NodeTransformer):
663 """Wraps all integers in a call to Integer()"""
664 """Wraps all integers in a call to Integer()"""
664 def visit_Num(self, node):
665 def visit_Num(self, node):
665 if isinstance(node.n, int):
666 if isinstance(node.n, int):
666 return ast.Call(func=ast.Name(id='Integer', ctx=ast.Load()),
667 return ast.Call(func=ast.Name(id='Integer', ctx=ast.Load()),
667 args=[node], keywords=[])
668 args=[node], keywords=[])
668 return node
669 return node
669
670
670 class TestAstTransform2(unittest.TestCase):
671 class TestAstTransform2(unittest.TestCase):
671 def setUp(self):
672 def setUp(self):
672 self.intwrapper = IntegerWrapper()
673 self.intwrapper = IntegerWrapper()
673 ip.ast_transformers.append(self.intwrapper)
674 ip.ast_transformers.append(self.intwrapper)
674
675
675 self.calls = []
676 self.calls = []
676 def Integer(*args):
677 def Integer(*args):
677 self.calls.append(args)
678 self.calls.append(args)
678 return args
679 return args
679 ip.push({"Integer": Integer})
680 ip.push({"Integer": Integer})
680
681
681 def tearDown(self):
682 def tearDown(self):
682 ip.ast_transformers.remove(self.intwrapper)
683 ip.ast_transformers.remove(self.intwrapper)
683 del ip.user_ns['Integer']
684 del ip.user_ns['Integer']
684
685
685 def test_run_cell(self):
686 def test_run_cell(self):
686 ip.run_cell("n = 2")
687 ip.run_cell("n = 2")
687 self.assertEqual(self.calls, [(2,)])
688 self.assertEqual(self.calls, [(2,)])
688
689
689 # This shouldn't throw an error
690 # This shouldn't throw an error
690 ip.run_cell("o = 2.0")
691 ip.run_cell("o = 2.0")
691 self.assertEqual(ip.user_ns['o'], 2.0)
692 self.assertEqual(ip.user_ns['o'], 2.0)
692
693
693 def test_timeit(self):
694 def test_timeit(self):
694 called = set()
695 called = set()
695 def f(x):
696 def f(x):
696 called.add(x)
697 called.add(x)
697 ip.push({'f':f})
698 ip.push({'f':f})
698
699
699 with tt.AssertPrints("std. dev. of"):
700 with tt.AssertPrints("std. dev. of"):
700 ip.run_line_magic("timeit", "-n1 f(1)")
701 ip.run_line_magic("timeit", "-n1 f(1)")
701 self.assertEqual(called, {(1,)})
702 self.assertEqual(called, {(1,)})
702 called.clear()
703 called.clear()
703
704
704 with tt.AssertPrints("std. dev. of"):
705 with tt.AssertPrints("std. dev. of"):
705 ip.run_cell_magic("timeit", "-n1 f(2)", "f(3)")
706 ip.run_cell_magic("timeit", "-n1 f(2)", "f(3)")
706 self.assertEqual(called, {(2,), (3,)})
707 self.assertEqual(called, {(2,), (3,)})
707
708
708 class ErrorTransformer(ast.NodeTransformer):
709 class ErrorTransformer(ast.NodeTransformer):
709 """Throws an error when it sees a number."""
710 """Throws an error when it sees a number."""
710 def visit_Num(self, node):
711 def visit_Num(self, node):
711 raise ValueError("test")
712 raise ValueError("test")
712
713
713 class TestAstTransformError(unittest.TestCase):
714 class TestAstTransformError(unittest.TestCase):
714 def test_unregistering(self):
715 def test_unregistering(self):
715 err_transformer = ErrorTransformer()
716 err_transformer = ErrorTransformer()
716 ip.ast_transformers.append(err_transformer)
717 ip.ast_transformers.append(err_transformer)
717
718
718 with tt.AssertPrints("unregister", channel='stderr'):
719 with tt.AssertPrints("unregister", channel='stderr'):
719 ip.run_cell("1 + 2")
720 ip.run_cell("1 + 2")
720
721
721 # This should have been removed.
722 # This should have been removed.
722 nt.assert_not_in(err_transformer, ip.ast_transformers)
723 nt.assert_not_in(err_transformer, ip.ast_transformers)
723
724
724
725
725 class StringRejector(ast.NodeTransformer):
726 class StringRejector(ast.NodeTransformer):
726 """Throws an InputRejected when it sees a string literal.
727 """Throws an InputRejected when it sees a string literal.
727
728
728 Used to verify that NodeTransformers can signal that a piece of code should
729 Used to verify that NodeTransformers can signal that a piece of code should
729 not be executed by throwing an InputRejected.
730 not be executed by throwing an InputRejected.
730 """
731 """
731
732
732 def visit_Str(self, node):
733 def visit_Str(self, node):
733 raise InputRejected("test")
734 raise InputRejected("test")
734
735
735
736
736 class TestAstTransformInputRejection(unittest.TestCase):
737 class TestAstTransformInputRejection(unittest.TestCase):
737
738
738 def setUp(self):
739 def setUp(self):
739 self.transformer = StringRejector()
740 self.transformer = StringRejector()
740 ip.ast_transformers.append(self.transformer)
741 ip.ast_transformers.append(self.transformer)
741
742
742 def tearDown(self):
743 def tearDown(self):
743 ip.ast_transformers.remove(self.transformer)
744 ip.ast_transformers.remove(self.transformer)
744
745
745 def test_input_rejection(self):
746 def test_input_rejection(self):
746 """Check that NodeTransformers can reject input."""
747 """Check that NodeTransformers can reject input."""
747
748
748 expect_exception_tb = tt.AssertPrints("InputRejected: test")
749 expect_exception_tb = tt.AssertPrints("InputRejected: test")
749 expect_no_cell_output = tt.AssertNotPrints("'unsafe'", suppress=False)
750 expect_no_cell_output = tt.AssertNotPrints("'unsafe'", suppress=False)
750
751
751 # Run the same check twice to verify that the transformer is not
752 # Run the same check twice to verify that the transformer is not
752 # disabled after raising.
753 # disabled after raising.
753 with expect_exception_tb, expect_no_cell_output:
754 with expect_exception_tb, expect_no_cell_output:
754 ip.run_cell("'unsafe'")
755 ip.run_cell("'unsafe'")
755
756
756 with expect_exception_tb, expect_no_cell_output:
757 with expect_exception_tb, expect_no_cell_output:
757 res = ip.run_cell("'unsafe'")
758 res = ip.run_cell("'unsafe'")
758
759
759 self.assertIsInstance(res.error_before_exec, InputRejected)
760 self.assertIsInstance(res.error_before_exec, InputRejected)
760
761
761 def test__IPYTHON__():
762 def test__IPYTHON__():
762 # This shouldn't raise a NameError, that's all
763 # This shouldn't raise a NameError, that's all
763 __IPYTHON__
764 __IPYTHON__
764
765
765
766
766 class DummyRepr(object):
767 class DummyRepr(object):
767 def __repr__(self):
768 def __repr__(self):
768 return "DummyRepr"
769 return "DummyRepr"
769
770
770 def _repr_html_(self):
771 def _repr_html_(self):
771 return "<b>dummy</b>"
772 return "<b>dummy</b>"
772
773
773 def _repr_javascript_(self):
774 def _repr_javascript_(self):
774 return "console.log('hi');", {'key': 'value'}
775 return "console.log('hi');", {'key': 'value'}
775
776
776
777
777 def test_user_variables():
778 def test_user_variables():
778 # enable all formatters
779 # enable all formatters
779 ip.display_formatter.active_types = ip.display_formatter.format_types
780 ip.display_formatter.active_types = ip.display_formatter.format_types
780
781
781 ip.user_ns['dummy'] = d = DummyRepr()
782 ip.user_ns['dummy'] = d = DummyRepr()
782 keys = {'dummy', 'doesnotexist'}
783 keys = {'dummy', 'doesnotexist'}
783 r = ip.user_expressions({ key:key for key in keys})
784 r = ip.user_expressions({ key:key for key in keys})
784
785
785 nt.assert_equal(keys, set(r.keys()))
786 nt.assert_equal(keys, set(r.keys()))
786 dummy = r['dummy']
787 dummy = r['dummy']
787 nt.assert_equal({'status', 'data', 'metadata'}, set(dummy.keys()))
788 nt.assert_equal({'status', 'data', 'metadata'}, set(dummy.keys()))
788 nt.assert_equal(dummy['status'], 'ok')
789 nt.assert_equal(dummy['status'], 'ok')
789 data = dummy['data']
790 data = dummy['data']
790 metadata = dummy['metadata']
791 metadata = dummy['metadata']
791 nt.assert_equal(data.get('text/html'), d._repr_html_())
792 nt.assert_equal(data.get('text/html'), d._repr_html_())
792 js, jsmd = d._repr_javascript_()
793 js, jsmd = d._repr_javascript_()
793 nt.assert_equal(data.get('application/javascript'), js)
794 nt.assert_equal(data.get('application/javascript'), js)
794 nt.assert_equal(metadata.get('application/javascript'), jsmd)
795 nt.assert_equal(metadata.get('application/javascript'), jsmd)
795
796
796 dne = r['doesnotexist']
797 dne = r['doesnotexist']
797 nt.assert_equal(dne['status'], 'error')
798 nt.assert_equal(dne['status'], 'error')
798 nt.assert_equal(dne['ename'], 'NameError')
799 nt.assert_equal(dne['ename'], 'NameError')
799
800
800 # back to text only
801 # back to text only
801 ip.display_formatter.active_types = ['text/plain']
802 ip.display_formatter.active_types = ['text/plain']
802
803
803 def test_user_expression():
804 def test_user_expression():
804 # enable all formatters
805 # enable all formatters
805 ip.display_formatter.active_types = ip.display_formatter.format_types
806 ip.display_formatter.active_types = ip.display_formatter.format_types
806 query = {
807 query = {
807 'a' : '1 + 2',
808 'a' : '1 + 2',
808 'b' : '1/0',
809 'b' : '1/0',
809 }
810 }
810 r = ip.user_expressions(query)
811 r = ip.user_expressions(query)
811 import pprint
812 import pprint
812 pprint.pprint(r)
813 pprint.pprint(r)
813 nt.assert_equal(set(r.keys()), set(query.keys()))
814 nt.assert_equal(set(r.keys()), set(query.keys()))
814 a = r['a']
815 a = r['a']
815 nt.assert_equal({'status', 'data', 'metadata'}, set(a.keys()))
816 nt.assert_equal({'status', 'data', 'metadata'}, set(a.keys()))
816 nt.assert_equal(a['status'], 'ok')
817 nt.assert_equal(a['status'], 'ok')
817 data = a['data']
818 data = a['data']
818 metadata = a['metadata']
819 metadata = a['metadata']
819 nt.assert_equal(data.get('text/plain'), '3')
820 nt.assert_equal(data.get('text/plain'), '3')
820
821
821 b = r['b']
822 b = r['b']
822 nt.assert_equal(b['status'], 'error')
823 nt.assert_equal(b['status'], 'error')
823 nt.assert_equal(b['ename'], 'ZeroDivisionError')
824 nt.assert_equal(b['ename'], 'ZeroDivisionError')
824
825
825 # back to text only
826 # back to text only
826 ip.display_formatter.active_types = ['text/plain']
827 ip.display_formatter.active_types = ['text/plain']
827
828
828
829
829
830
830
831
831
832
832 class TestSyntaxErrorTransformer(unittest.TestCase):
833 class TestSyntaxErrorTransformer(unittest.TestCase):
833 """Check that SyntaxError raised by an input transformer is handled by run_cell()"""
834 """Check that SyntaxError raised by an input transformer is handled by run_cell()"""
834
835
835 @staticmethod
836 @staticmethod
836 def transformer(lines):
837 def transformer(lines):
837 for line in lines:
838 for line in lines:
838 pos = line.find('syntaxerror')
839 pos = line.find('syntaxerror')
839 if pos >= 0:
840 if pos >= 0:
840 e = SyntaxError('input contains "syntaxerror"')
841 e = SyntaxError('input contains "syntaxerror"')
841 e.text = line
842 e.text = line
842 e.offset = pos + 1
843 e.offset = pos + 1
843 raise e
844 raise e
844 return lines
845 return lines
845
846
846 def setUp(self):
847 def setUp(self):
847 ip.input_transformers_post.append(self.transformer)
848 ip.input_transformers_post.append(self.transformer)
848
849
849 def tearDown(self):
850 def tearDown(self):
850 ip.input_transformers_post.remove(self.transformer)
851 ip.input_transformers_post.remove(self.transformer)
851
852
852 def test_syntaxerror_input_transformer(self):
853 def test_syntaxerror_input_transformer(self):
853 with tt.AssertPrints('1234'):
854 with tt.AssertPrints('1234'):
854 ip.run_cell('1234')
855 ip.run_cell('1234')
855 with tt.AssertPrints('SyntaxError: invalid syntax'):
856 with tt.AssertPrints('SyntaxError: invalid syntax'):
856 ip.run_cell('1 2 3') # plain python syntax error
857 ip.run_cell('1 2 3') # plain python syntax error
857 with tt.AssertPrints('SyntaxError: input contains "syntaxerror"'):
858 with tt.AssertPrints('SyntaxError: input contains "syntaxerror"'):
858 ip.run_cell('2345 # syntaxerror') # input transformer syntax error
859 ip.run_cell('2345 # syntaxerror') # input transformer syntax error
859 with tt.AssertPrints('3456'):
860 with tt.AssertPrints('3456'):
860 ip.run_cell('3456')
861 ip.run_cell('3456')
861
862
862
863
863
864
864 def test_warning_suppression():
865 def test_warning_suppression():
865 ip.run_cell("import warnings")
866 ip.run_cell("import warnings")
866 try:
867 try:
867 with tt.AssertPrints("UserWarning: asdf", channel="stderr"):
868 with tt.AssertPrints("UserWarning: asdf", channel="stderr"):
868 ip.run_cell("warnings.warn('asdf')")
869 ip.run_cell("warnings.warn('asdf')")
869 # Here's the real test -- if we run that again, we should get the
870 # Here's the real test -- if we run that again, we should get the
870 # warning again. Traditionally, each warning was only issued once per
871 # warning again. Traditionally, each warning was only issued once per
871 # IPython session (approximately), even if the user typed in new and
872 # IPython session (approximately), even if the user typed in new and
872 # different code that should have also triggered the warning, leading
873 # different code that should have also triggered the warning, leading
873 # to much confusion.
874 # to much confusion.
874 with tt.AssertPrints("UserWarning: asdf", channel="stderr"):
875 with tt.AssertPrints("UserWarning: asdf", channel="stderr"):
875 ip.run_cell("warnings.warn('asdf')")
876 ip.run_cell("warnings.warn('asdf')")
876 finally:
877 finally:
877 ip.run_cell("del warnings")
878 ip.run_cell("del warnings")
878
879
879
880
880 def test_deprecation_warning():
881 def test_deprecation_warning():
881 ip.run_cell("""
882 ip.run_cell("""
882 import warnings
883 import warnings
883 def wrn():
884 def wrn():
884 warnings.warn(
885 warnings.warn(
885 "I AM A WARNING",
886 "I AM A WARNING",
886 DeprecationWarning
887 DeprecationWarning
887 )
888 )
888 """)
889 """)
889 try:
890 try:
890 with tt.AssertPrints("I AM A WARNING", channel="stderr"):
891 with tt.AssertPrints("I AM A WARNING", channel="stderr"):
891 ip.run_cell("wrn()")
892 ip.run_cell("wrn()")
892 finally:
893 finally:
893 ip.run_cell("del warnings")
894 ip.run_cell("del warnings")
894 ip.run_cell("del wrn")
895 ip.run_cell("del wrn")
895
896
896
897
897 class TestImportNoDeprecate(tt.TempFileMixin):
898 class TestImportNoDeprecate(tt.TempFileMixin):
898
899
899 def setup(self):
900 def setup(self):
900 """Make a valid python temp file."""
901 """Make a valid python temp file."""
901 self.mktmp("""
902 self.mktmp("""
902 import warnings
903 import warnings
903 def wrn():
904 def wrn():
904 warnings.warn(
905 warnings.warn(
905 "I AM A WARNING",
906 "I AM A WARNING",
906 DeprecationWarning
907 DeprecationWarning
907 )
908 )
908 """)
909 """)
909
910
910 def test_no_dep(self):
911 def test_no_dep(self):
911 """
912 """
912 No deprecation warning should be raised from imported functions
913 No deprecation warning should be raised from imported functions
913 """
914 """
914 ip.run_cell("from {} import wrn".format(self.fname))
915 ip.run_cell("from {} import wrn".format(self.fname))
915
916
916 with tt.AssertNotPrints("I AM A WARNING"):
917 with tt.AssertNotPrints("I AM A WARNING"):
917 ip.run_cell("wrn()")
918 ip.run_cell("wrn()")
918 ip.run_cell("del wrn")
919 ip.run_cell("del wrn")
919
920
920
921
921 def test_custom_exc_count():
922 def test_custom_exc_count():
922 hook = mock.Mock(return_value=None)
923 hook = mock.Mock(return_value=None)
923 ip.set_custom_exc((SyntaxError,), hook)
924 ip.set_custom_exc((SyntaxError,), hook)
924 before = ip.execution_count
925 before = ip.execution_count
925 ip.run_cell("def foo()", store_history=True)
926 ip.run_cell("def foo()", store_history=True)
926 # restore default excepthook
927 # restore default excepthook
927 ip.set_custom_exc((), None)
928 ip.set_custom_exc((), None)
928 nt.assert_equal(hook.call_count, 1)
929 nt.assert_equal(hook.call_count, 1)
929 nt.assert_equal(ip.execution_count, before + 1)
930 nt.assert_equal(ip.execution_count, before + 1)
@@ -1,60 +1,60 b''
1 # -*- coding: utf-8 -*-
1 # -*- coding: utf-8 -*-
2 """Tests for shellapp module.
2 """Tests for shellapp module.
3
3
4 Authors
4 Authors
5 -------
5 -------
6 * Bradley Froehle
6 * Bradley Froehle
7 """
7 """
8 #-----------------------------------------------------------------------------
8 #-----------------------------------------------------------------------------
9 # Copyright (C) 2012 The IPython Development Team
9 # Copyright (C) 2012 The IPython Development Team
10 #
10 #
11 # Distributed under the terms of the BSD License. The full license is in
11 # Distributed under the terms of the BSD License. The full license is in
12 # the file COPYING, distributed as part of this software.
12 # the file COPYING, distributed as part of this software.
13 #-----------------------------------------------------------------------------
13 #-----------------------------------------------------------------------------
14
14
15 #-----------------------------------------------------------------------------
15 #-----------------------------------------------------------------------------
16 # Imports
16 # Imports
17 #-----------------------------------------------------------------------------
17 #-----------------------------------------------------------------------------
18 import unittest
18 import unittest
19
19
20 from IPython.testing import decorators as dec
20 from IPython.testing import decorators as dec
21 from IPython.testing import tools as tt
21 from IPython.testing import tools as tt
22
22
23 sqlite_err_maybe = dec.module_not_available('sqlite3')
23 sqlite_err_maybe = dec.module_not_available('sqlite3')
24 SQLITE_NOT_AVAILABLE_ERROR = ('WARNING: IPython History requires SQLite,'
24 SQLITE_NOT_AVAILABLE_ERROR = ('WARNING: IPython History requires SQLite,'
25 ' your history will not be saved\n')
25 ' your history will not be saved\n')
26
26
27 class TestFileToRun(unittest.TestCase, tt.TempFileMixin):
27 class TestFileToRun(tt.TempFileMixin, unittest.TestCase):
28 """Test the behavior of the file_to_run parameter."""
28 """Test the behavior of the file_to_run parameter."""
29
29
30 def test_py_script_file_attribute(self):
30 def test_py_script_file_attribute(self):
31 """Test that `__file__` is set when running `ipython file.py`"""
31 """Test that `__file__` is set when running `ipython file.py`"""
32 src = "print(__file__)\n"
32 src = "print(__file__)\n"
33 self.mktmp(src)
33 self.mktmp(src)
34
34
35 err = SQLITE_NOT_AVAILABLE_ERROR if sqlite_err_maybe else None
35 err = SQLITE_NOT_AVAILABLE_ERROR if sqlite_err_maybe else None
36 tt.ipexec_validate(self.fname, self.fname, err)
36 tt.ipexec_validate(self.fname, self.fname, err)
37
37
38 def test_ipy_script_file_attribute(self):
38 def test_ipy_script_file_attribute(self):
39 """Test that `__file__` is set when running `ipython file.ipy`"""
39 """Test that `__file__` is set when running `ipython file.ipy`"""
40 src = "print(__file__)\n"
40 src = "print(__file__)\n"
41 self.mktmp(src, ext='.ipy')
41 self.mktmp(src, ext='.ipy')
42
42
43 err = SQLITE_NOT_AVAILABLE_ERROR if sqlite_err_maybe else None
43 err = SQLITE_NOT_AVAILABLE_ERROR if sqlite_err_maybe else None
44 tt.ipexec_validate(self.fname, self.fname, err)
44 tt.ipexec_validate(self.fname, self.fname, err)
45
45
46 # The commands option to ipexec_validate doesn't work on Windows, and it
46 # The commands option to ipexec_validate doesn't work on Windows, and it
47 # doesn't seem worth fixing
47 # doesn't seem worth fixing
48 @dec.skip_win32
48 @dec.skip_win32
49 def test_py_script_file_attribute_interactively(self):
49 def test_py_script_file_attribute_interactively(self):
50 """Test that `__file__` is not set after `ipython -i file.py`"""
50 """Test that `__file__` is not set after `ipython -i file.py`"""
51 src = "True\n"
51 src = "True\n"
52 self.mktmp(src)
52 self.mktmp(src)
53
53
54 out, err = tt.ipexec(self.fname, options=['-i'],
54 out, err = tt.ipexec(self.fname, options=['-i'],
55 commands=['"__file__" in globals()', 'print(123)', 'exit()'])
55 commands=['"__file__" in globals()', 'print(123)', 'exit()'])
56 if 'False' not in out:
56 if 'False' not in out:
57 print("Subprocess stderr:")
57 print("Subprocess stderr:")
58 print(err)
58 print(err)
59 print('-----')
59 print('-----')
60 raise AssertionError("'False' not found in %r" % out)
60 raise AssertionError("'False' not found in %r" % out)
@@ -1,341 +1,341 b''
1 # -*- coding: utf-8 -*-
1 # -*- coding: utf-8 -*-
2 """Usage information for the main IPython applications.
2 """Usage information for the main IPython applications.
3 """
3 """
4 #-----------------------------------------------------------------------------
4 #-----------------------------------------------------------------------------
5 # Copyright (C) 2008-2011 The IPython Development Team
5 # Copyright (C) 2008-2011 The IPython Development Team
6 # Copyright (C) 2001-2007 Fernando Perez. <fperez@colorado.edu>
6 # Copyright (C) 2001-2007 Fernando Perez. <fperez@colorado.edu>
7 #
7 #
8 # Distributed under the terms of the BSD License. The full license is in
8 # Distributed under the terms of the BSD License. The full license is in
9 # the file COPYING, distributed as part of this software.
9 # the file COPYING, distributed as part of this software.
10 #-----------------------------------------------------------------------------
10 #-----------------------------------------------------------------------------
11
11
12 import sys
12 import sys
13 from IPython.core import release
13 from IPython.core import release
14
14
15 cl_usage = """\
15 cl_usage = """\
16 =========
16 =========
17 IPython
17 IPython
18 =========
18 =========
19
19
20 Tools for Interactive Computing in Python
20 Tools for Interactive Computing in Python
21 =========================================
21 =========================================
22
22
23 A Python shell with automatic history (input and output), dynamic object
23 A Python shell with automatic history (input and output), dynamic object
24 introspection, easier configuration, command completion, access to the
24 introspection, easier configuration, command completion, access to the
25 system shell and more. IPython can also be embedded in running programs.
25 system shell and more. IPython can also be embedded in running programs.
26
26
27
27
28 Usage
28 Usage
29
29
30 ipython [subcommand] [options] [-c cmd | -m mod | file] [--] [arg] ...
30 ipython [subcommand] [options] [-c cmd | -m mod | file] [--] [arg] ...
31
31
32 If invoked with no options, it executes the file and exits, passing the
32 If invoked with no options, it executes the file and exits, passing the
33 remaining arguments to the script, just as if you had specified the same
33 remaining arguments to the script, just as if you had specified the same
34 command with python. You may need to specify `--` before args to be passed
34 command with python. You may need to specify `--` before args to be passed
35 to the script, to prevent IPython from attempting to parse them. If you
35 to the script, to prevent IPython from attempting to parse them. If you
36 specify the option `-i` before the filename, it will enter an interactive
36 specify the option `-i` before the filename, it will enter an interactive
37 IPython session after running the script, rather than exiting. Files ending
37 IPython session after running the script, rather than exiting. Files ending
38 in .py will be treated as normal Python, but files ending in .ipy can
38 in .py will be treated as normal Python, but files ending in .ipy can
39 contain special IPython syntax (magic commands, shell expansions, etc.).
39 contain special IPython syntax (magic commands, shell expansions, etc.).
40
40
41 Almost all configuration in IPython is available via the command-line. Do
41 Almost all configuration in IPython is available via the command-line. Do
42 `ipython --help-all` to see all available options. For persistent
42 `ipython --help-all` to see all available options. For persistent
43 configuration, look into your `ipython_config.py` configuration file for
43 configuration, look into your `ipython_config.py` configuration file for
44 details.
44 details.
45
45
46 This file is typically installed in the `IPYTHONDIR` directory, and there
46 This file is typically installed in the `IPYTHONDIR` directory, and there
47 is a separate configuration directory for each profile. The default profile
47 is a separate configuration directory for each profile. The default profile
48 directory will be located in $IPYTHONDIR/profile_default. IPYTHONDIR
48 directory will be located in $IPYTHONDIR/profile_default. IPYTHONDIR
49 defaults to to `$HOME/.ipython`. For Windows users, $HOME resolves to
49 defaults to to `$HOME/.ipython`. For Windows users, $HOME resolves to
50 C:\\Users\\YourUserName in most instances.
50 C:\\Users\\YourUserName in most instances.
51
51
52 To initialize a profile with the default configuration file, do::
52 To initialize a profile with the default configuration file, do::
53
53
54 $> ipython profile create
54 $> ipython profile create
55
55
56 and start editing `IPYTHONDIR/profile_default/ipython_config.py`
56 and start editing `IPYTHONDIR/profile_default/ipython_config.py`
57
57
58 In IPython's documentation, we will refer to this directory as
58 In IPython's documentation, we will refer to this directory as
59 `IPYTHONDIR`, you can change its default location by creating an
59 `IPYTHONDIR`, you can change its default location by creating an
60 environment variable with this name and setting it to the desired path.
60 environment variable with this name and setting it to the desired path.
61
61
62 For more information, see the manual available in HTML and PDF in your
62 For more information, see the manual available in HTML and PDF in your
63 installation, or online at http://ipython.org/documentation.html.
63 installation, or online at https://ipython.org/documentation.html.
64 """
64 """
65
65
66 interactive_usage = """
66 interactive_usage = """
67 IPython -- An enhanced Interactive Python
67 IPython -- An enhanced Interactive Python
68 =========================================
68 =========================================
69
69
70 IPython offers a fully compatible replacement for the standard Python
70 IPython offers a fully compatible replacement for the standard Python
71 interpreter, with convenient shell features, special commands, command
71 interpreter, with convenient shell features, special commands, command
72 history mechanism and output results caching.
72 history mechanism and output results caching.
73
73
74 At your system command line, type 'ipython -h' to see the command line
74 At your system command line, type 'ipython -h' to see the command line
75 options available. This document only describes interactive features.
75 options available. This document only describes interactive features.
76
76
77 GETTING HELP
77 GETTING HELP
78 ------------
78 ------------
79
79
80 Within IPython you have various way to access help:
80 Within IPython you have various way to access help:
81
81
82 ? -> Introduction and overview of IPython's features (this screen).
82 ? -> Introduction and overview of IPython's features (this screen).
83 object? -> Details about 'object'.
83 object? -> Details about 'object'.
84 object?? -> More detailed, verbose information about 'object'.
84 object?? -> More detailed, verbose information about 'object'.
85 %quickref -> Quick reference of all IPython specific syntax and magics.
85 %quickref -> Quick reference of all IPython specific syntax and magics.
86 help -> Access Python's own help system.
86 help -> Access Python's own help system.
87
87
88 If you are in terminal IPython you can quit this screen by pressing `q`.
88 If you are in terminal IPython you can quit this screen by pressing `q`.
89
89
90
90
91 MAIN FEATURES
91 MAIN FEATURES
92 -------------
92 -------------
93
93
94 * Access to the standard Python help with object docstrings and the Python
94 * Access to the standard Python help with object docstrings and the Python
95 manuals. Simply type 'help' (no quotes) to invoke it.
95 manuals. Simply type 'help' (no quotes) to invoke it.
96
96
97 * Magic commands: type %magic for information on the magic subsystem.
97 * Magic commands: type %magic for information on the magic subsystem.
98
98
99 * System command aliases, via the %alias command or the configuration file(s).
99 * System command aliases, via the %alias command or the configuration file(s).
100
100
101 * Dynamic object information:
101 * Dynamic object information:
102
102
103 Typing ?word or word? prints detailed information about an object. Certain
103 Typing ?word or word? prints detailed information about an object. Certain
104 long strings (code, etc.) get snipped in the center for brevity.
104 long strings (code, etc.) get snipped in the center for brevity.
105
105
106 Typing ??word or word?? gives access to the full information without
106 Typing ??word or word?? gives access to the full information without
107 snipping long strings. Strings that are longer than the screen are printed
107 snipping long strings. Strings that are longer than the screen are printed
108 through the less pager.
108 through the less pager.
109
109
110 The ?/?? system gives access to the full source code for any object (if
110 The ?/?? system gives access to the full source code for any object (if
111 available), shows function prototypes and other useful information.
111 available), shows function prototypes and other useful information.
112
112
113 If you just want to see an object's docstring, type '%pdoc object' (without
113 If you just want to see an object's docstring, type '%pdoc object' (without
114 quotes, and without % if you have automagic on).
114 quotes, and without % if you have automagic on).
115
115
116 * Tab completion in the local namespace:
116 * Tab completion in the local namespace:
117
117
118 At any time, hitting tab will complete any available python commands or
118 At any time, hitting tab will complete any available python commands or
119 variable names, and show you a list of the possible completions if there's
119 variable names, and show you a list of the possible completions if there's
120 no unambiguous one. It will also complete filenames in the current directory.
120 no unambiguous one. It will also complete filenames in the current directory.
121
121
122 * Search previous command history in multiple ways:
122 * Search previous command history in multiple ways:
123
123
124 - Start typing, and then use arrow keys up/down or (Ctrl-p/Ctrl-n) to search
124 - Start typing, and then use arrow keys up/down or (Ctrl-p/Ctrl-n) to search
125 through the history items that match what you've typed so far.
125 through the history items that match what you've typed so far.
126
126
127 - Hit Ctrl-r: opens a search prompt. Begin typing and the system searches
127 - Hit Ctrl-r: opens a search prompt. Begin typing and the system searches
128 your history for lines that match what you've typed so far, completing as
128 your history for lines that match what you've typed so far, completing as
129 much as it can.
129 much as it can.
130
130
131 - %hist: search history by index.
131 - %hist: search history by index.
132
132
133 * Persistent command history across sessions.
133 * Persistent command history across sessions.
134
134
135 * Logging of input with the ability to save and restore a working session.
135 * Logging of input with the ability to save and restore a working session.
136
136
137 * System shell with !. Typing !ls will run 'ls' in the current directory.
137 * System shell with !. Typing !ls will run 'ls' in the current directory.
138
138
139 * The reload command does a 'deep' reload of a module: changes made to the
139 * The reload command does a 'deep' reload of a module: changes made to the
140 module since you imported will actually be available without having to exit.
140 module since you imported will actually be available without having to exit.
141
141
142 * Verbose and colored exception traceback printouts. See the magic xmode and
142 * Verbose and colored exception traceback printouts. See the magic xmode and
143 xcolor functions for details (just type %magic).
143 xcolor functions for details (just type %magic).
144
144
145 * Input caching system:
145 * Input caching system:
146
146
147 IPython offers numbered prompts (In/Out) with input and output caching. All
147 IPython offers numbered prompts (In/Out) with input and output caching. All
148 input is saved and can be retrieved as variables (besides the usual arrow
148 input is saved and can be retrieved as variables (besides the usual arrow
149 key recall).
149 key recall).
150
150
151 The following GLOBAL variables always exist (so don't overwrite them!):
151 The following GLOBAL variables always exist (so don't overwrite them!):
152 _i: stores previous input.
152 _i: stores previous input.
153 _ii: next previous.
153 _ii: next previous.
154 _iii: next-next previous.
154 _iii: next-next previous.
155 _ih : a list of all input _ih[n] is the input from line n.
155 _ih : a list of all input _ih[n] is the input from line n.
156
156
157 Additionally, global variables named _i<n> are dynamically created (<n>
157 Additionally, global variables named _i<n> are dynamically created (<n>
158 being the prompt counter), such that _i<n> == _ih[<n>]
158 being the prompt counter), such that _i<n> == _ih[<n>]
159
159
160 For example, what you typed at prompt 14 is available as _i14 and _ih[14].
160 For example, what you typed at prompt 14 is available as _i14 and _ih[14].
161
161
162 You can create macros which contain multiple input lines from this history,
162 You can create macros which contain multiple input lines from this history,
163 for later re-execution, with the %macro function.
163 for later re-execution, with the %macro function.
164
164
165 The history function %hist allows you to see any part of your input history
165 The history function %hist allows you to see any part of your input history
166 by printing a range of the _i variables. Note that inputs which contain
166 by printing a range of the _i variables. Note that inputs which contain
167 magic functions (%) appear in the history with a prepended comment. This is
167 magic functions (%) appear in the history with a prepended comment. This is
168 because they aren't really valid Python code, so you can't exec them.
168 because they aren't really valid Python code, so you can't exec them.
169
169
170 * Output caching system:
170 * Output caching system:
171
171
172 For output that is returned from actions, a system similar to the input
172 For output that is returned from actions, a system similar to the input
173 cache exists but using _ instead of _i. Only actions that produce a result
173 cache exists but using _ instead of _i. Only actions that produce a result
174 (NOT assignments, for example) are cached. If you are familiar with
174 (NOT assignments, for example) are cached. If you are familiar with
175 Mathematica, IPython's _ variables behave exactly like Mathematica's %
175 Mathematica, IPython's _ variables behave exactly like Mathematica's %
176 variables.
176 variables.
177
177
178 The following GLOBAL variables always exist (so don't overwrite them!):
178 The following GLOBAL variables always exist (so don't overwrite them!):
179 _ (one underscore): previous output.
179 _ (one underscore): previous output.
180 __ (two underscores): next previous.
180 __ (two underscores): next previous.
181 ___ (three underscores): next-next previous.
181 ___ (three underscores): next-next previous.
182
182
183 Global variables named _<n> are dynamically created (<n> being the prompt
183 Global variables named _<n> are dynamically created (<n> being the prompt
184 counter), such that the result of output <n> is always available as _<n>.
184 counter), such that the result of output <n> is always available as _<n>.
185
185
186 Finally, a global dictionary named _oh exists with entries for all lines
186 Finally, a global dictionary named _oh exists with entries for all lines
187 which generated output.
187 which generated output.
188
188
189 * Directory history:
189 * Directory history:
190
190
191 Your history of visited directories is kept in the global list _dh, and the
191 Your history of visited directories is kept in the global list _dh, and the
192 magic %cd command can be used to go to any entry in that list.
192 magic %cd command can be used to go to any entry in that list.
193
193
194 * Auto-parentheses and auto-quotes (adapted from Nathan Gray's LazyPython)
194 * Auto-parentheses and auto-quotes (adapted from Nathan Gray's LazyPython)
195
195
196 1. Auto-parentheses
196 1. Auto-parentheses
197
197
198 Callable objects (i.e. functions, methods, etc) can be invoked like
198 Callable objects (i.e. functions, methods, etc) can be invoked like
199 this (notice the commas between the arguments)::
199 this (notice the commas between the arguments)::
200
200
201 In [1]: callable_ob arg1, arg2, arg3
201 In [1]: callable_ob arg1, arg2, arg3
202
202
203 and the input will be translated to this::
203 and the input will be translated to this::
204
204
205 callable_ob(arg1, arg2, arg3)
205 callable_ob(arg1, arg2, arg3)
206
206
207 This feature is off by default (in rare cases it can produce
207 This feature is off by default (in rare cases it can produce
208 undesirable side-effects), but you can activate it at the command-line
208 undesirable side-effects), but you can activate it at the command-line
209 by starting IPython with `--autocall 1`, set it permanently in your
209 by starting IPython with `--autocall 1`, set it permanently in your
210 configuration file, or turn on at runtime with `%autocall 1`.
210 configuration file, or turn on at runtime with `%autocall 1`.
211
211
212 You can force auto-parentheses by using '/' as the first character
212 You can force auto-parentheses by using '/' as the first character
213 of a line. For example::
213 of a line. For example::
214
214
215 In [1]: /globals # becomes 'globals()'
215 In [1]: /globals # becomes 'globals()'
216
216
217 Note that the '/' MUST be the first character on the line! This
217 Note that the '/' MUST be the first character on the line! This
218 won't work::
218 won't work::
219
219
220 In [2]: print /globals # syntax error
220 In [2]: print /globals # syntax error
221
221
222 In most cases the automatic algorithm should work, so you should
222 In most cases the automatic algorithm should work, so you should
223 rarely need to explicitly invoke /. One notable exception is if you
223 rarely need to explicitly invoke /. One notable exception is if you
224 are trying to call a function with a list of tuples as arguments (the
224 are trying to call a function with a list of tuples as arguments (the
225 parenthesis will confuse IPython)::
225 parenthesis will confuse IPython)::
226
226
227 In [1]: zip (1,2,3),(4,5,6) # won't work
227 In [1]: zip (1,2,3),(4,5,6) # won't work
228
228
229 but this will work::
229 but this will work::
230
230
231 In [2]: /zip (1,2,3),(4,5,6)
231 In [2]: /zip (1,2,3),(4,5,6)
232 ------> zip ((1,2,3),(4,5,6))
232 ------> zip ((1,2,3),(4,5,6))
233 Out[2]= [(1, 4), (2, 5), (3, 6)]
233 Out[2]= [(1, 4), (2, 5), (3, 6)]
234
234
235 IPython tells you that it has altered your command line by
235 IPython tells you that it has altered your command line by
236 displaying the new command line preceded by -->. e.g.::
236 displaying the new command line preceded by -->. e.g.::
237
237
238 In [18]: callable list
238 In [18]: callable list
239 -------> callable (list)
239 -------> callable (list)
240
240
241 2. Auto-Quoting
241 2. Auto-Quoting
242
242
243 You can force auto-quoting of a function's arguments by using ',' as
243 You can force auto-quoting of a function's arguments by using ',' as
244 the first character of a line. For example::
244 the first character of a line. For example::
245
245
246 In [1]: ,my_function /home/me # becomes my_function("/home/me")
246 In [1]: ,my_function /home/me # becomes my_function("/home/me")
247
247
248 If you use ';' instead, the whole argument is quoted as a single
248 If you use ';' instead, the whole argument is quoted as a single
249 string (while ',' splits on whitespace)::
249 string (while ',' splits on whitespace)::
250
250
251 In [2]: ,my_function a b c # becomes my_function("a","b","c")
251 In [2]: ,my_function a b c # becomes my_function("a","b","c")
252 In [3]: ;my_function a b c # becomes my_function("a b c")
252 In [3]: ;my_function a b c # becomes my_function("a b c")
253
253
254 Note that the ',' MUST be the first character on the line! This
254 Note that the ',' MUST be the first character on the line! This
255 won't work::
255 won't work::
256
256
257 In [4]: x = ,my_function /home/me # syntax error
257 In [4]: x = ,my_function /home/me # syntax error
258 """
258 """
259
259
260 interactive_usage_min = """\
260 interactive_usage_min = """\
261 An enhanced console for Python.
261 An enhanced console for Python.
262 Some of its features are:
262 Some of its features are:
263 - Tab completion in the local namespace.
263 - Tab completion in the local namespace.
264 - Logging of input, see command-line options.
264 - Logging of input, see command-line options.
265 - System shell escape via ! , eg !ls.
265 - System shell escape via ! , eg !ls.
266 - Magic commands, starting with a % (like %ls, %pwd, %cd, etc.)
266 - Magic commands, starting with a % (like %ls, %pwd, %cd, etc.)
267 - Keeps track of locally defined variables via %who, %whos.
267 - Keeps track of locally defined variables via %who, %whos.
268 - Show object information with a ? eg ?x or x? (use ?? for more info).
268 - Show object information with a ? eg ?x or x? (use ?? for more info).
269 """
269 """
270
270
271 quick_reference = r"""
271 quick_reference = r"""
272 IPython -- An enhanced Interactive Python - Quick Reference Card
272 IPython -- An enhanced Interactive Python - Quick Reference Card
273 ================================================================
273 ================================================================
274
274
275 obj?, obj?? : Get help, or more help for object (also works as
275 obj?, obj?? : Get help, or more help for object (also works as
276 ?obj, ??obj).
276 ?obj, ??obj).
277 ?foo.*abc* : List names in 'foo' containing 'abc' in them.
277 ?foo.*abc* : List names in 'foo' containing 'abc' in them.
278 %magic : Information about IPython's 'magic' % functions.
278 %magic : Information about IPython's 'magic' % functions.
279
279
280 Magic functions are prefixed by % or %%, and typically take their arguments
280 Magic functions are prefixed by % or %%, and typically take their arguments
281 without parentheses, quotes or even commas for convenience. Line magics take a
281 without parentheses, quotes or even commas for convenience. Line magics take a
282 single % and cell magics are prefixed with two %%.
282 single % and cell magics are prefixed with two %%.
283
283
284 Example magic function calls:
284 Example magic function calls:
285
285
286 %alias d ls -F : 'd' is now an alias for 'ls -F'
286 %alias d ls -F : 'd' is now an alias for 'ls -F'
287 alias d ls -F : Works if 'alias' not a python name
287 alias d ls -F : Works if 'alias' not a python name
288 alist = %alias : Get list of aliases to 'alist'
288 alist = %alias : Get list of aliases to 'alist'
289 cd /usr/share : Obvious. cd -<tab> to choose from visited dirs.
289 cd /usr/share : Obvious. cd -<tab> to choose from visited dirs.
290 %cd?? : See help AND source for magic %cd
290 %cd?? : See help AND source for magic %cd
291 %timeit x=10 : time the 'x=10' statement with high precision.
291 %timeit x=10 : time the 'x=10' statement with high precision.
292 %%timeit x=2**100
292 %%timeit x=2**100
293 x**100 : time 'x**100' with a setup of 'x=2**100'; setup code is not
293 x**100 : time 'x**100' with a setup of 'x=2**100'; setup code is not
294 counted. This is an example of a cell magic.
294 counted. This is an example of a cell magic.
295
295
296 System commands:
296 System commands:
297
297
298 !cp a.txt b/ : System command escape, calls os.system()
298 !cp a.txt b/ : System command escape, calls os.system()
299 cp a.txt b/ : after %rehashx, most system commands work without !
299 cp a.txt b/ : after %rehashx, most system commands work without !
300 cp ${f}.txt $bar : Variable expansion in magics and system commands
300 cp ${f}.txt $bar : Variable expansion in magics and system commands
301 files = !ls /usr : Capture system command output
301 files = !ls /usr : Capture system command output
302 files.s, files.l, files.n: "a b c", ['a','b','c'], 'a\nb\nc'
302 files.s, files.l, files.n: "a b c", ['a','b','c'], 'a\nb\nc'
303
303
304 History:
304 History:
305
305
306 _i, _ii, _iii : Previous, next previous, next next previous input
306 _i, _ii, _iii : Previous, next previous, next next previous input
307 _i4, _ih[2:5] : Input history line 4, lines 2-4
307 _i4, _ih[2:5] : Input history line 4, lines 2-4
308 exec _i81 : Execute input history line #81 again
308 exec _i81 : Execute input history line #81 again
309 %rep 81 : Edit input history line #81
309 %rep 81 : Edit input history line #81
310 _, __, ___ : previous, next previous, next next previous output
310 _, __, ___ : previous, next previous, next next previous output
311 _dh : Directory history
311 _dh : Directory history
312 _oh : Output history
312 _oh : Output history
313 %hist : Command history of current session.
313 %hist : Command history of current session.
314 %hist -g foo : Search command history of (almost) all sessions for 'foo'.
314 %hist -g foo : Search command history of (almost) all sessions for 'foo'.
315 %hist -g : Command history of (almost) all sessions.
315 %hist -g : Command history of (almost) all sessions.
316 %hist 1/2-8 : Command history containing lines 2-8 of session 1.
316 %hist 1/2-8 : Command history containing lines 2-8 of session 1.
317 %hist 1/ ~2/ : Command history of session 1 and 2 sessions before current.
317 %hist 1/ ~2/ : Command history of session 1 and 2 sessions before current.
318 %hist ~8/1-~6/5 : Command history from line 1 of 8 sessions ago to
318 %hist ~8/1-~6/5 : Command history from line 1 of 8 sessions ago to
319 line 5 of 6 sessions ago.
319 line 5 of 6 sessions ago.
320 %edit 0/ : Open editor to execute code with history of current session.
320 %edit 0/ : Open editor to execute code with history of current session.
321
321
322 Autocall:
322 Autocall:
323
323
324 f 1,2 : f(1,2) # Off by default, enable with %autocall magic.
324 f 1,2 : f(1,2) # Off by default, enable with %autocall magic.
325 /f 1,2 : f(1,2) (forced autoparen)
325 /f 1,2 : f(1,2) (forced autoparen)
326 ,f 1 2 : f("1","2")
326 ,f 1 2 : f("1","2")
327 ;f 1 2 : f("1 2")
327 ;f 1 2 : f("1 2")
328
328
329 Remember: TAB completion works in many contexts, not just file names
329 Remember: TAB completion works in many contexts, not just file names
330 or python names.
330 or python names.
331
331
332 The following magic functions are currently available:
332 The following magic functions are currently available:
333
333
334 """
334 """
335
335
336 default_banner_parts = ["Python %s\n"%sys.version.split("\n")[0],
336 default_banner_parts = ["Python %s\n"%sys.version.split("\n")[0],
337 "Type 'copyright', 'credits' or 'license' for more information\n" ,
337 "Type 'copyright', 'credits' or 'license' for more information\n" ,
338 "IPython {version} -- An enhanced Interactive Python. Type '?' for help.\n".format(version=release.version),
338 "IPython {version} -- An enhanced Interactive Python. Type '?' for help.\n".format(version=release.version),
339 ]
339 ]
340
340
341 default_banner = ''.join(default_banner_parts)
341 default_banner = ''.join(default_banner_parts)
@@ -1,871 +1,871 b''
1 # -*- coding: utf-8 -*-
1 # -*- coding: utf-8 -*-
2 """
2 """
3 Python advanced pretty printer. This pretty printer is intended to
3 Python advanced pretty printer. This pretty printer is intended to
4 replace the old `pprint` python module which does not allow developers
4 replace the old `pprint` python module which does not allow developers
5 to provide their own pretty print callbacks.
5 to provide their own pretty print callbacks.
6
6
7 This module is based on ruby's `prettyprint.rb` library by `Tanaka Akira`.
7 This module is based on ruby's `prettyprint.rb` library by `Tanaka Akira`.
8
8
9
9
10 Example Usage
10 Example Usage
11 -------------
11 -------------
12
12
13 To directly print the representation of an object use `pprint`::
13 To directly print the representation of an object use `pprint`::
14
14
15 from pretty import pprint
15 from pretty import pprint
16 pprint(complex_object)
16 pprint(complex_object)
17
17
18 To get a string of the output use `pretty`::
18 To get a string of the output use `pretty`::
19
19
20 from pretty import pretty
20 from pretty import pretty
21 string = pretty(complex_object)
21 string = pretty(complex_object)
22
22
23
23
24 Extending
24 Extending
25 ---------
25 ---------
26
26
27 The pretty library allows developers to add pretty printing rules for their
27 The pretty library allows developers to add pretty printing rules for their
28 own objects. This process is straightforward. All you have to do is to
28 own objects. This process is straightforward. All you have to do is to
29 add a `_repr_pretty_` method to your object and call the methods on the
29 add a `_repr_pretty_` method to your object and call the methods on the
30 pretty printer passed::
30 pretty printer passed::
31
31
32 class MyObject(object):
32 class MyObject(object):
33
33
34 def _repr_pretty_(self, p, cycle):
34 def _repr_pretty_(self, p, cycle):
35 ...
35 ...
36
36
37 Here is an example implementation of a `_repr_pretty_` method for a list
37 Here is an example implementation of a `_repr_pretty_` method for a list
38 subclass::
38 subclass::
39
39
40 class MyList(list):
40 class MyList(list):
41
41
42 def _repr_pretty_(self, p, cycle):
42 def _repr_pretty_(self, p, cycle):
43 if cycle:
43 if cycle:
44 p.text('MyList(...)')
44 p.text('MyList(...)')
45 else:
45 else:
46 with p.group(8, 'MyList([', '])'):
46 with p.group(8, 'MyList([', '])'):
47 for idx, item in enumerate(self):
47 for idx, item in enumerate(self):
48 if idx:
48 if idx:
49 p.text(',')
49 p.text(',')
50 p.breakable()
50 p.breakable()
51 p.pretty(item)
51 p.pretty(item)
52
52
53 The `cycle` parameter is `True` if pretty detected a cycle. You *have* to
53 The `cycle` parameter is `True` if pretty detected a cycle. You *have* to
54 react to that or the result is an infinite loop. `p.text()` just adds
54 react to that or the result is an infinite loop. `p.text()` just adds
55 non breaking text to the output, `p.breakable()` either adds a whitespace
55 non breaking text to the output, `p.breakable()` either adds a whitespace
56 or breaks here. If you pass it an argument it's used instead of the
56 or breaks here. If you pass it an argument it's used instead of the
57 default space. `p.pretty` prettyprints another object using the pretty print
57 default space. `p.pretty` prettyprints another object using the pretty print
58 method.
58 method.
59
59
60 The first parameter to the `group` function specifies the extra indentation
60 The first parameter to the `group` function specifies the extra indentation
61 of the next line. In this example the next item will either be on the same
61 of the next line. In this example the next item will either be on the same
62 line (if the items are short enough) or aligned with the right edge of the
62 line (if the items are short enough) or aligned with the right edge of the
63 opening bracket of `MyList`.
63 opening bracket of `MyList`.
64
64
65 If you just want to indent something you can use the group function
65 If you just want to indent something you can use the group function
66 without open / close parameters. You can also use this code::
66 without open / close parameters. You can also use this code::
67
67
68 with p.indent(2):
68 with p.indent(2):
69 ...
69 ...
70
70
71 Inheritance diagram:
71 Inheritance diagram:
72
72
73 .. inheritance-diagram:: IPython.lib.pretty
73 .. inheritance-diagram:: IPython.lib.pretty
74 :parts: 3
74 :parts: 3
75
75
76 :copyright: 2007 by Armin Ronacher.
76 :copyright: 2007 by Armin Ronacher.
77 Portions (c) 2009 by Robert Kern.
77 Portions (c) 2009 by Robert Kern.
78 :license: BSD License.
78 :license: BSD License.
79 """
79 """
80
80
81 from contextlib import contextmanager
81 from contextlib import contextmanager
82 import datetime
82 import datetime
83 import os
83 import os
84 import re
84 import re
85 import sys
85 import sys
86 import types
86 import types
87 from collections import deque
87 from collections import deque
88 from inspect import signature
88 from io import StringIO
89 from io import StringIO
89 from warnings import warn
90 from warnings import warn
90
91
91 from IPython.utils.decorators import undoc
92 from IPython.utils.decorators import undoc
92 from IPython.utils.py3compat import PYPY
93 from IPython.utils.py3compat import PYPY
93 from IPython.utils.signatures import signature
94
94
95 __all__ = ['pretty', 'pprint', 'PrettyPrinter', 'RepresentationPrinter',
95 __all__ = ['pretty', 'pprint', 'PrettyPrinter', 'RepresentationPrinter',
96 'for_type', 'for_type_by_name']
96 'for_type', 'for_type_by_name']
97
97
98
98
99 MAX_SEQ_LENGTH = 1000
99 MAX_SEQ_LENGTH = 1000
100 # The language spec says that dicts preserve order from 3.7, but CPython
100 # The language spec says that dicts preserve order from 3.7, but CPython
101 # does so from 3.6, so it seems likely that people will expect that.
101 # does so from 3.6, so it seems likely that people will expect that.
102 DICT_IS_ORDERED = sys.version_info >= (3, 6)
102 DICT_IS_ORDERED = sys.version_info >= (3, 6)
103 _re_pattern_type = type(re.compile(''))
103 _re_pattern_type = type(re.compile(''))
104
104
105 def _safe_getattr(obj, attr, default=None):
105 def _safe_getattr(obj, attr, default=None):
106 """Safe version of getattr.
106 """Safe version of getattr.
107
107
108 Same as getattr, but will return ``default`` on any Exception,
108 Same as getattr, but will return ``default`` on any Exception,
109 rather than raising.
109 rather than raising.
110 """
110 """
111 try:
111 try:
112 return getattr(obj, attr, default)
112 return getattr(obj, attr, default)
113 except Exception:
113 except Exception:
114 return default
114 return default
115
115
116 @undoc
116 @undoc
117 class CUnicodeIO(StringIO):
117 class CUnicodeIO(StringIO):
118 def __init__(self, *args, **kwargs):
118 def __init__(self, *args, **kwargs):
119 super().__init__(*args, **kwargs)
119 super().__init__(*args, **kwargs)
120 warn(("CUnicodeIO is deprecated since IPython 6.0. "
120 warn(("CUnicodeIO is deprecated since IPython 6.0. "
121 "Please use io.StringIO instead."),
121 "Please use io.StringIO instead."),
122 DeprecationWarning, stacklevel=2)
122 DeprecationWarning, stacklevel=2)
123
123
124 def _sorted_for_pprint(items):
124 def _sorted_for_pprint(items):
125 """
125 """
126 Sort the given items for pretty printing. Since some predictable
126 Sort the given items for pretty printing. Since some predictable
127 sorting is better than no sorting at all, we sort on the string
127 sorting is better than no sorting at all, we sort on the string
128 representation if normal sorting fails.
128 representation if normal sorting fails.
129 """
129 """
130 items = list(items)
130 items = list(items)
131 try:
131 try:
132 return sorted(items)
132 return sorted(items)
133 except Exception:
133 except Exception:
134 try:
134 try:
135 return sorted(items, key=str)
135 return sorted(items, key=str)
136 except Exception:
136 except Exception:
137 return items
137 return items
138
138
139 def pretty(obj, verbose=False, max_width=79, newline='\n', max_seq_length=MAX_SEQ_LENGTH):
139 def pretty(obj, verbose=False, max_width=79, newline='\n', max_seq_length=MAX_SEQ_LENGTH):
140 """
140 """
141 Pretty print the object's representation.
141 Pretty print the object's representation.
142 """
142 """
143 stream = StringIO()
143 stream = StringIO()
144 printer = RepresentationPrinter(stream, verbose, max_width, newline, max_seq_length=max_seq_length)
144 printer = RepresentationPrinter(stream, verbose, max_width, newline, max_seq_length=max_seq_length)
145 printer.pretty(obj)
145 printer.pretty(obj)
146 printer.flush()
146 printer.flush()
147 return stream.getvalue()
147 return stream.getvalue()
148
148
149
149
150 def pprint(obj, verbose=False, max_width=79, newline='\n', max_seq_length=MAX_SEQ_LENGTH):
150 def pprint(obj, verbose=False, max_width=79, newline='\n', max_seq_length=MAX_SEQ_LENGTH):
151 """
151 """
152 Like `pretty` but print to stdout.
152 Like `pretty` but print to stdout.
153 """
153 """
154 printer = RepresentationPrinter(sys.stdout, verbose, max_width, newline, max_seq_length=max_seq_length)
154 printer = RepresentationPrinter(sys.stdout, verbose, max_width, newline, max_seq_length=max_seq_length)
155 printer.pretty(obj)
155 printer.pretty(obj)
156 printer.flush()
156 printer.flush()
157 sys.stdout.write(newline)
157 sys.stdout.write(newline)
158 sys.stdout.flush()
158 sys.stdout.flush()
159
159
160 class _PrettyPrinterBase(object):
160 class _PrettyPrinterBase(object):
161
161
162 @contextmanager
162 @contextmanager
163 def indent(self, indent):
163 def indent(self, indent):
164 """with statement support for indenting/dedenting."""
164 """with statement support for indenting/dedenting."""
165 self.indentation += indent
165 self.indentation += indent
166 try:
166 try:
167 yield
167 yield
168 finally:
168 finally:
169 self.indentation -= indent
169 self.indentation -= indent
170
170
171 @contextmanager
171 @contextmanager
172 def group(self, indent=0, open='', close=''):
172 def group(self, indent=0, open='', close=''):
173 """like begin_group / end_group but for the with statement."""
173 """like begin_group / end_group but for the with statement."""
174 self.begin_group(indent, open)
174 self.begin_group(indent, open)
175 try:
175 try:
176 yield
176 yield
177 finally:
177 finally:
178 self.end_group(indent, close)
178 self.end_group(indent, close)
179
179
180 class PrettyPrinter(_PrettyPrinterBase):
180 class PrettyPrinter(_PrettyPrinterBase):
181 """
181 """
182 Baseclass for the `RepresentationPrinter` prettyprinter that is used to
182 Baseclass for the `RepresentationPrinter` prettyprinter that is used to
183 generate pretty reprs of objects. Contrary to the `RepresentationPrinter`
183 generate pretty reprs of objects. Contrary to the `RepresentationPrinter`
184 this printer knows nothing about the default pprinters or the `_repr_pretty_`
184 this printer knows nothing about the default pprinters or the `_repr_pretty_`
185 callback method.
185 callback method.
186 """
186 """
187
187
188 def __init__(self, output, max_width=79, newline='\n', max_seq_length=MAX_SEQ_LENGTH):
188 def __init__(self, output, max_width=79, newline='\n', max_seq_length=MAX_SEQ_LENGTH):
189 self.output = output
189 self.output = output
190 self.max_width = max_width
190 self.max_width = max_width
191 self.newline = newline
191 self.newline = newline
192 self.max_seq_length = max_seq_length
192 self.max_seq_length = max_seq_length
193 self.output_width = 0
193 self.output_width = 0
194 self.buffer_width = 0
194 self.buffer_width = 0
195 self.buffer = deque()
195 self.buffer = deque()
196
196
197 root_group = Group(0)
197 root_group = Group(0)
198 self.group_stack = [root_group]
198 self.group_stack = [root_group]
199 self.group_queue = GroupQueue(root_group)
199 self.group_queue = GroupQueue(root_group)
200 self.indentation = 0
200 self.indentation = 0
201
201
202 def _break_outer_groups(self):
202 def _break_outer_groups(self):
203 while self.max_width < self.output_width + self.buffer_width:
203 while self.max_width < self.output_width + self.buffer_width:
204 group = self.group_queue.deq()
204 group = self.group_queue.deq()
205 if not group:
205 if not group:
206 return
206 return
207 while group.breakables:
207 while group.breakables:
208 x = self.buffer.popleft()
208 x = self.buffer.popleft()
209 self.output_width = x.output(self.output, self.output_width)
209 self.output_width = x.output(self.output, self.output_width)
210 self.buffer_width -= x.width
210 self.buffer_width -= x.width
211 while self.buffer and isinstance(self.buffer[0], Text):
211 while self.buffer and isinstance(self.buffer[0], Text):
212 x = self.buffer.popleft()
212 x = self.buffer.popleft()
213 self.output_width = x.output(self.output, self.output_width)
213 self.output_width = x.output(self.output, self.output_width)
214 self.buffer_width -= x.width
214 self.buffer_width -= x.width
215
215
216 def text(self, obj):
216 def text(self, obj):
217 """Add literal text to the output."""
217 """Add literal text to the output."""
218 width = len(obj)
218 width = len(obj)
219 if self.buffer:
219 if self.buffer:
220 text = self.buffer[-1]
220 text = self.buffer[-1]
221 if not isinstance(text, Text):
221 if not isinstance(text, Text):
222 text = Text()
222 text = Text()
223 self.buffer.append(text)
223 self.buffer.append(text)
224 text.add(obj, width)
224 text.add(obj, width)
225 self.buffer_width += width
225 self.buffer_width += width
226 self._break_outer_groups()
226 self._break_outer_groups()
227 else:
227 else:
228 self.output.write(obj)
228 self.output.write(obj)
229 self.output_width += width
229 self.output_width += width
230
230
231 def breakable(self, sep=' '):
231 def breakable(self, sep=' '):
232 """
232 """
233 Add a breakable separator to the output. This does not mean that it
233 Add a breakable separator to the output. This does not mean that it
234 will automatically break here. If no breaking on this position takes
234 will automatically break here. If no breaking on this position takes
235 place the `sep` is inserted which default to one space.
235 place the `sep` is inserted which default to one space.
236 """
236 """
237 width = len(sep)
237 width = len(sep)
238 group = self.group_stack[-1]
238 group = self.group_stack[-1]
239 if group.want_break:
239 if group.want_break:
240 self.flush()
240 self.flush()
241 self.output.write(self.newline)
241 self.output.write(self.newline)
242 self.output.write(' ' * self.indentation)
242 self.output.write(' ' * self.indentation)
243 self.output_width = self.indentation
243 self.output_width = self.indentation
244 self.buffer_width = 0
244 self.buffer_width = 0
245 else:
245 else:
246 self.buffer.append(Breakable(sep, width, self))
246 self.buffer.append(Breakable(sep, width, self))
247 self.buffer_width += width
247 self.buffer_width += width
248 self._break_outer_groups()
248 self._break_outer_groups()
249
249
250 def break_(self):
250 def break_(self):
251 """
251 """
252 Explicitly insert a newline into the output, maintaining correct indentation.
252 Explicitly insert a newline into the output, maintaining correct indentation.
253 """
253 """
254 self.flush()
254 self.flush()
255 self.output.write(self.newline)
255 self.output.write(self.newline)
256 self.output.write(' ' * self.indentation)
256 self.output.write(' ' * self.indentation)
257 self.output_width = self.indentation
257 self.output_width = self.indentation
258 self.buffer_width = 0
258 self.buffer_width = 0
259
259
260
260
261 def begin_group(self, indent=0, open=''):
261 def begin_group(self, indent=0, open=''):
262 """
262 """
263 Begin a group. If you want support for python < 2.5 which doesn't has
263 Begin a group. If you want support for python < 2.5 which doesn't has
264 the with statement this is the preferred way:
264 the with statement this is the preferred way:
265
265
266 p.begin_group(1, '{')
266 p.begin_group(1, '{')
267 ...
267 ...
268 p.end_group(1, '}')
268 p.end_group(1, '}')
269
269
270 The python 2.5 expression would be this:
270 The python 2.5 expression would be this:
271
271
272 with p.group(1, '{', '}'):
272 with p.group(1, '{', '}'):
273 ...
273 ...
274
274
275 The first parameter specifies the indentation for the next line (usually
275 The first parameter specifies the indentation for the next line (usually
276 the width of the opening text), the second the opening text. All
276 the width of the opening text), the second the opening text. All
277 parameters are optional.
277 parameters are optional.
278 """
278 """
279 if open:
279 if open:
280 self.text(open)
280 self.text(open)
281 group = Group(self.group_stack[-1].depth + 1)
281 group = Group(self.group_stack[-1].depth + 1)
282 self.group_stack.append(group)
282 self.group_stack.append(group)
283 self.group_queue.enq(group)
283 self.group_queue.enq(group)
284 self.indentation += indent
284 self.indentation += indent
285
285
286 def _enumerate(self, seq):
286 def _enumerate(self, seq):
287 """like enumerate, but with an upper limit on the number of items"""
287 """like enumerate, but with an upper limit on the number of items"""
288 for idx, x in enumerate(seq):
288 for idx, x in enumerate(seq):
289 if self.max_seq_length and idx >= self.max_seq_length:
289 if self.max_seq_length and idx >= self.max_seq_length:
290 self.text(',')
290 self.text(',')
291 self.breakable()
291 self.breakable()
292 self.text('...')
292 self.text('...')
293 return
293 return
294 yield idx, x
294 yield idx, x
295
295
296 def end_group(self, dedent=0, close=''):
296 def end_group(self, dedent=0, close=''):
297 """End a group. See `begin_group` for more details."""
297 """End a group. See `begin_group` for more details."""
298 self.indentation -= dedent
298 self.indentation -= dedent
299 group = self.group_stack.pop()
299 group = self.group_stack.pop()
300 if not group.breakables:
300 if not group.breakables:
301 self.group_queue.remove(group)
301 self.group_queue.remove(group)
302 if close:
302 if close:
303 self.text(close)
303 self.text(close)
304
304
305 def flush(self):
305 def flush(self):
306 """Flush data that is left in the buffer."""
306 """Flush data that is left in the buffer."""
307 for data in self.buffer:
307 for data in self.buffer:
308 self.output_width += data.output(self.output, self.output_width)
308 self.output_width += data.output(self.output, self.output_width)
309 self.buffer.clear()
309 self.buffer.clear()
310 self.buffer_width = 0
310 self.buffer_width = 0
311
311
312
312
313 def _get_mro(obj_class):
313 def _get_mro(obj_class):
314 """ Get a reasonable method resolution order of a class and its superclasses
314 """ Get a reasonable method resolution order of a class and its superclasses
315 for both old-style and new-style classes.
315 for both old-style and new-style classes.
316 """
316 """
317 if not hasattr(obj_class, '__mro__'):
317 if not hasattr(obj_class, '__mro__'):
318 # Old-style class. Mix in object to make a fake new-style class.
318 # Old-style class. Mix in object to make a fake new-style class.
319 try:
319 try:
320 obj_class = type(obj_class.__name__, (obj_class, object), {})
320 obj_class = type(obj_class.__name__, (obj_class, object), {})
321 except TypeError:
321 except TypeError:
322 # Old-style extension type that does not descend from object.
322 # Old-style extension type that does not descend from object.
323 # FIXME: try to construct a more thorough MRO.
323 # FIXME: try to construct a more thorough MRO.
324 mro = [obj_class]
324 mro = [obj_class]
325 else:
325 else:
326 mro = obj_class.__mro__[1:-1]
326 mro = obj_class.__mro__[1:-1]
327 else:
327 else:
328 mro = obj_class.__mro__
328 mro = obj_class.__mro__
329 return mro
329 return mro
330
330
331
331
332 class RepresentationPrinter(PrettyPrinter):
332 class RepresentationPrinter(PrettyPrinter):
333 """
333 """
334 Special pretty printer that has a `pretty` method that calls the pretty
334 Special pretty printer that has a `pretty` method that calls the pretty
335 printer for a python object.
335 printer for a python object.
336
336
337 This class stores processing data on `self` so you must *never* use
337 This class stores processing data on `self` so you must *never* use
338 this class in a threaded environment. Always lock it or reinstanciate
338 this class in a threaded environment. Always lock it or reinstanciate
339 it.
339 it.
340
340
341 Instances also have a verbose flag callbacks can access to control their
341 Instances also have a verbose flag callbacks can access to control their
342 output. For example the default instance repr prints all attributes and
342 output. For example the default instance repr prints all attributes and
343 methods that are not prefixed by an underscore if the printer is in
343 methods that are not prefixed by an underscore if the printer is in
344 verbose mode.
344 verbose mode.
345 """
345 """
346
346
347 def __init__(self, output, verbose=False, max_width=79, newline='\n',
347 def __init__(self, output, verbose=False, max_width=79, newline='\n',
348 singleton_pprinters=None, type_pprinters=None, deferred_pprinters=None,
348 singleton_pprinters=None, type_pprinters=None, deferred_pprinters=None,
349 max_seq_length=MAX_SEQ_LENGTH):
349 max_seq_length=MAX_SEQ_LENGTH):
350
350
351 PrettyPrinter.__init__(self, output, max_width, newline, max_seq_length=max_seq_length)
351 PrettyPrinter.__init__(self, output, max_width, newline, max_seq_length=max_seq_length)
352 self.verbose = verbose
352 self.verbose = verbose
353 self.stack = []
353 self.stack = []
354 if singleton_pprinters is None:
354 if singleton_pprinters is None:
355 singleton_pprinters = _singleton_pprinters.copy()
355 singleton_pprinters = _singleton_pprinters.copy()
356 self.singleton_pprinters = singleton_pprinters
356 self.singleton_pprinters = singleton_pprinters
357 if type_pprinters is None:
357 if type_pprinters is None:
358 type_pprinters = _type_pprinters.copy()
358 type_pprinters = _type_pprinters.copy()
359 self.type_pprinters = type_pprinters
359 self.type_pprinters = type_pprinters
360 if deferred_pprinters is None:
360 if deferred_pprinters is None:
361 deferred_pprinters = _deferred_type_pprinters.copy()
361 deferred_pprinters = _deferred_type_pprinters.copy()
362 self.deferred_pprinters = deferred_pprinters
362 self.deferred_pprinters = deferred_pprinters
363
363
364 def pretty(self, obj):
364 def pretty(self, obj):
365 """Pretty print the given object."""
365 """Pretty print the given object."""
366 obj_id = id(obj)
366 obj_id = id(obj)
367 cycle = obj_id in self.stack
367 cycle = obj_id in self.stack
368 self.stack.append(obj_id)
368 self.stack.append(obj_id)
369 self.begin_group()
369 self.begin_group()
370 try:
370 try:
371 obj_class = _safe_getattr(obj, '__class__', None) or type(obj)
371 obj_class = _safe_getattr(obj, '__class__', None) or type(obj)
372 # First try to find registered singleton printers for the type.
372 # First try to find registered singleton printers for the type.
373 try:
373 try:
374 printer = self.singleton_pprinters[obj_id]
374 printer = self.singleton_pprinters[obj_id]
375 except (TypeError, KeyError):
375 except (TypeError, KeyError):
376 pass
376 pass
377 else:
377 else:
378 return printer(obj, self, cycle)
378 return printer(obj, self, cycle)
379 # Next walk the mro and check for either:
379 # Next walk the mro and check for either:
380 # 1) a registered printer
380 # 1) a registered printer
381 # 2) a _repr_pretty_ method
381 # 2) a _repr_pretty_ method
382 for cls in _get_mro(obj_class):
382 for cls in _get_mro(obj_class):
383 if cls in self.type_pprinters:
383 if cls in self.type_pprinters:
384 # printer registered in self.type_pprinters
384 # printer registered in self.type_pprinters
385 return self.type_pprinters[cls](obj, self, cycle)
385 return self.type_pprinters[cls](obj, self, cycle)
386 else:
386 else:
387 # deferred printer
387 # deferred printer
388 printer = self._in_deferred_types(cls)
388 printer = self._in_deferred_types(cls)
389 if printer is not None:
389 if printer is not None:
390 return printer(obj, self, cycle)
390 return printer(obj, self, cycle)
391 else:
391 else:
392 # Finally look for special method names.
392 # Finally look for special method names.
393 # Some objects automatically create any requested
393 # Some objects automatically create any requested
394 # attribute. Try to ignore most of them by checking for
394 # attribute. Try to ignore most of them by checking for
395 # callability.
395 # callability.
396 if '_repr_pretty_' in cls.__dict__:
396 if '_repr_pretty_' in cls.__dict__:
397 meth = cls._repr_pretty_
397 meth = cls._repr_pretty_
398 if callable(meth):
398 if callable(meth):
399 return meth(obj, self, cycle)
399 return meth(obj, self, cycle)
400 if cls is not object \
400 if cls is not object \
401 and callable(cls.__dict__.get('__repr__')):
401 and callable(cls.__dict__.get('__repr__')):
402 return _repr_pprint(obj, self, cycle)
402 return _repr_pprint(obj, self, cycle)
403
403
404 return _default_pprint(obj, self, cycle)
404 return _default_pprint(obj, self, cycle)
405 finally:
405 finally:
406 self.end_group()
406 self.end_group()
407 self.stack.pop()
407 self.stack.pop()
408
408
409 def _in_deferred_types(self, cls):
409 def _in_deferred_types(self, cls):
410 """
410 """
411 Check if the given class is specified in the deferred type registry.
411 Check if the given class is specified in the deferred type registry.
412
412
413 Returns the printer from the registry if it exists, and None if the
413 Returns the printer from the registry if it exists, and None if the
414 class is not in the registry. Successful matches will be moved to the
414 class is not in the registry. Successful matches will be moved to the
415 regular type registry for future use.
415 regular type registry for future use.
416 """
416 """
417 mod = _safe_getattr(cls, '__module__', None)
417 mod = _safe_getattr(cls, '__module__', None)
418 name = _safe_getattr(cls, '__name__', None)
418 name = _safe_getattr(cls, '__name__', None)
419 key = (mod, name)
419 key = (mod, name)
420 printer = None
420 printer = None
421 if key in self.deferred_pprinters:
421 if key in self.deferred_pprinters:
422 # Move the printer over to the regular registry.
422 # Move the printer over to the regular registry.
423 printer = self.deferred_pprinters.pop(key)
423 printer = self.deferred_pprinters.pop(key)
424 self.type_pprinters[cls] = printer
424 self.type_pprinters[cls] = printer
425 return printer
425 return printer
426
426
427
427
428 class Printable(object):
428 class Printable(object):
429
429
430 def output(self, stream, output_width):
430 def output(self, stream, output_width):
431 return output_width
431 return output_width
432
432
433
433
434 class Text(Printable):
434 class Text(Printable):
435
435
436 def __init__(self):
436 def __init__(self):
437 self.objs = []
437 self.objs = []
438 self.width = 0
438 self.width = 0
439
439
440 def output(self, stream, output_width):
440 def output(self, stream, output_width):
441 for obj in self.objs:
441 for obj in self.objs:
442 stream.write(obj)
442 stream.write(obj)
443 return output_width + self.width
443 return output_width + self.width
444
444
445 def add(self, obj, width):
445 def add(self, obj, width):
446 self.objs.append(obj)
446 self.objs.append(obj)
447 self.width += width
447 self.width += width
448
448
449
449
450 class Breakable(Printable):
450 class Breakable(Printable):
451
451
452 def __init__(self, seq, width, pretty):
452 def __init__(self, seq, width, pretty):
453 self.obj = seq
453 self.obj = seq
454 self.width = width
454 self.width = width
455 self.pretty = pretty
455 self.pretty = pretty
456 self.indentation = pretty.indentation
456 self.indentation = pretty.indentation
457 self.group = pretty.group_stack[-1]
457 self.group = pretty.group_stack[-1]
458 self.group.breakables.append(self)
458 self.group.breakables.append(self)
459
459
460 def output(self, stream, output_width):
460 def output(self, stream, output_width):
461 self.group.breakables.popleft()
461 self.group.breakables.popleft()
462 if self.group.want_break:
462 if self.group.want_break:
463 stream.write(self.pretty.newline)
463 stream.write(self.pretty.newline)
464 stream.write(' ' * self.indentation)
464 stream.write(' ' * self.indentation)
465 return self.indentation
465 return self.indentation
466 if not self.group.breakables:
466 if not self.group.breakables:
467 self.pretty.group_queue.remove(self.group)
467 self.pretty.group_queue.remove(self.group)
468 stream.write(self.obj)
468 stream.write(self.obj)
469 return output_width + self.width
469 return output_width + self.width
470
470
471
471
472 class Group(Printable):
472 class Group(Printable):
473
473
474 def __init__(self, depth):
474 def __init__(self, depth):
475 self.depth = depth
475 self.depth = depth
476 self.breakables = deque()
476 self.breakables = deque()
477 self.want_break = False
477 self.want_break = False
478
478
479
479
480 class GroupQueue(object):
480 class GroupQueue(object):
481
481
482 def __init__(self, *groups):
482 def __init__(self, *groups):
483 self.queue = []
483 self.queue = []
484 for group in groups:
484 for group in groups:
485 self.enq(group)
485 self.enq(group)
486
486
487 def enq(self, group):
487 def enq(self, group):
488 depth = group.depth
488 depth = group.depth
489 while depth > len(self.queue) - 1:
489 while depth > len(self.queue) - 1:
490 self.queue.append([])
490 self.queue.append([])
491 self.queue[depth].append(group)
491 self.queue[depth].append(group)
492
492
493 def deq(self):
493 def deq(self):
494 for stack in self.queue:
494 for stack in self.queue:
495 for idx, group in enumerate(reversed(stack)):
495 for idx, group in enumerate(reversed(stack)):
496 if group.breakables:
496 if group.breakables:
497 del stack[idx]
497 del stack[idx]
498 group.want_break = True
498 group.want_break = True
499 return group
499 return group
500 for group in stack:
500 for group in stack:
501 group.want_break = True
501 group.want_break = True
502 del stack[:]
502 del stack[:]
503
503
504 def remove(self, group):
504 def remove(self, group):
505 try:
505 try:
506 self.queue[group.depth].remove(group)
506 self.queue[group.depth].remove(group)
507 except ValueError:
507 except ValueError:
508 pass
508 pass
509
509
510
510
511 def _default_pprint(obj, p, cycle):
511 def _default_pprint(obj, p, cycle):
512 """
512 """
513 The default print function. Used if an object does not provide one and
513 The default print function. Used if an object does not provide one and
514 it's none of the builtin objects.
514 it's none of the builtin objects.
515 """
515 """
516 klass = _safe_getattr(obj, '__class__', None) or type(obj)
516 klass = _safe_getattr(obj, '__class__', None) or type(obj)
517 if _safe_getattr(klass, '__repr__', None) is not object.__repr__:
517 if _safe_getattr(klass, '__repr__', None) is not object.__repr__:
518 # A user-provided repr. Find newlines and replace them with p.break_()
518 # A user-provided repr. Find newlines and replace them with p.break_()
519 _repr_pprint(obj, p, cycle)
519 _repr_pprint(obj, p, cycle)
520 return
520 return
521 p.begin_group(1, '<')
521 p.begin_group(1, '<')
522 p.pretty(klass)
522 p.pretty(klass)
523 p.text(' at 0x%x' % id(obj))
523 p.text(' at 0x%x' % id(obj))
524 if cycle:
524 if cycle:
525 p.text(' ...')
525 p.text(' ...')
526 elif p.verbose:
526 elif p.verbose:
527 first = True
527 first = True
528 for key in dir(obj):
528 for key in dir(obj):
529 if not key.startswith('_'):
529 if not key.startswith('_'):
530 try:
530 try:
531 value = getattr(obj, key)
531 value = getattr(obj, key)
532 except AttributeError:
532 except AttributeError:
533 continue
533 continue
534 if isinstance(value, types.MethodType):
534 if isinstance(value, types.MethodType):
535 continue
535 continue
536 if not first:
536 if not first:
537 p.text(',')
537 p.text(',')
538 p.breakable()
538 p.breakable()
539 p.text(key)
539 p.text(key)
540 p.text('=')
540 p.text('=')
541 step = len(key) + 1
541 step = len(key) + 1
542 p.indentation += step
542 p.indentation += step
543 p.pretty(value)
543 p.pretty(value)
544 p.indentation -= step
544 p.indentation -= step
545 first = False
545 first = False
546 p.end_group(1, '>')
546 p.end_group(1, '>')
547
547
548
548
549 def _seq_pprinter_factory(start, end):
549 def _seq_pprinter_factory(start, end):
550 """
550 """
551 Factory that returns a pprint function useful for sequences. Used by
551 Factory that returns a pprint function useful for sequences. Used by
552 the default pprint for tuples, dicts, and lists.
552 the default pprint for tuples, dicts, and lists.
553 """
553 """
554 def inner(obj, p, cycle):
554 def inner(obj, p, cycle):
555 if cycle:
555 if cycle:
556 return p.text(start + '...' + end)
556 return p.text(start + '...' + end)
557 step = len(start)
557 step = len(start)
558 p.begin_group(step, start)
558 p.begin_group(step, start)
559 for idx, x in p._enumerate(obj):
559 for idx, x in p._enumerate(obj):
560 if idx:
560 if idx:
561 p.text(',')
561 p.text(',')
562 p.breakable()
562 p.breakable()
563 p.pretty(x)
563 p.pretty(x)
564 if len(obj) == 1 and type(obj) is tuple:
564 if len(obj) == 1 and type(obj) is tuple:
565 # Special case for 1-item tuples.
565 # Special case for 1-item tuples.
566 p.text(',')
566 p.text(',')
567 p.end_group(step, end)
567 p.end_group(step, end)
568 return inner
568 return inner
569
569
570
570
571 def _set_pprinter_factory(start, end):
571 def _set_pprinter_factory(start, end):
572 """
572 """
573 Factory that returns a pprint function useful for sets and frozensets.
573 Factory that returns a pprint function useful for sets and frozensets.
574 """
574 """
575 def inner(obj, p, cycle):
575 def inner(obj, p, cycle):
576 if cycle:
576 if cycle:
577 return p.text(start + '...' + end)
577 return p.text(start + '...' + end)
578 if len(obj) == 0:
578 if len(obj) == 0:
579 # Special case.
579 # Special case.
580 p.text(type(obj).__name__ + '()')
580 p.text(type(obj).__name__ + '()')
581 else:
581 else:
582 step = len(start)
582 step = len(start)
583 p.begin_group(step, start)
583 p.begin_group(step, start)
584 # Like dictionary keys, we will try to sort the items if there aren't too many
584 # Like dictionary keys, we will try to sort the items if there aren't too many
585 if not (p.max_seq_length and len(obj) >= p.max_seq_length):
585 if not (p.max_seq_length and len(obj) >= p.max_seq_length):
586 items = _sorted_for_pprint(obj)
586 items = _sorted_for_pprint(obj)
587 else:
587 else:
588 items = obj
588 items = obj
589 for idx, x in p._enumerate(items):
589 for idx, x in p._enumerate(items):
590 if idx:
590 if idx:
591 p.text(',')
591 p.text(',')
592 p.breakable()
592 p.breakable()
593 p.pretty(x)
593 p.pretty(x)
594 p.end_group(step, end)
594 p.end_group(step, end)
595 return inner
595 return inner
596
596
597
597
598 def _dict_pprinter_factory(start, end):
598 def _dict_pprinter_factory(start, end):
599 """
599 """
600 Factory that returns a pprint function used by the default pprint of
600 Factory that returns a pprint function used by the default pprint of
601 dicts and dict proxies.
601 dicts and dict proxies.
602 """
602 """
603 def inner(obj, p, cycle):
603 def inner(obj, p, cycle):
604 if cycle:
604 if cycle:
605 return p.text('{...}')
605 return p.text('{...}')
606 step = len(start)
606 step = len(start)
607 p.begin_group(step, start)
607 p.begin_group(step, start)
608 keys = obj.keys()
608 keys = obj.keys()
609 # if dict isn't large enough to be truncated, sort keys before displaying
609 # if dict isn't large enough to be truncated, sort keys before displaying
610 # From Python 3.7, dicts preserve order by definition, so we don't sort.
610 # From Python 3.7, dicts preserve order by definition, so we don't sort.
611 if not DICT_IS_ORDERED \
611 if not DICT_IS_ORDERED \
612 and not (p.max_seq_length and len(obj) >= p.max_seq_length):
612 and not (p.max_seq_length and len(obj) >= p.max_seq_length):
613 keys = _sorted_for_pprint(keys)
613 keys = _sorted_for_pprint(keys)
614 for idx, key in p._enumerate(keys):
614 for idx, key in p._enumerate(keys):
615 if idx:
615 if idx:
616 p.text(',')
616 p.text(',')
617 p.breakable()
617 p.breakable()
618 p.pretty(key)
618 p.pretty(key)
619 p.text(': ')
619 p.text(': ')
620 p.pretty(obj[key])
620 p.pretty(obj[key])
621 p.end_group(step, end)
621 p.end_group(step, end)
622 return inner
622 return inner
623
623
624
624
625 def _super_pprint(obj, p, cycle):
625 def _super_pprint(obj, p, cycle):
626 """The pprint for the super type."""
626 """The pprint for the super type."""
627 p.begin_group(8, '<super: ')
627 p.begin_group(8, '<super: ')
628 p.pretty(obj.__thisclass__)
628 p.pretty(obj.__thisclass__)
629 p.text(',')
629 p.text(',')
630 p.breakable()
630 p.breakable()
631 if PYPY: # In PyPy, super() objects don't have __self__ attributes
631 if PYPY: # In PyPy, super() objects don't have __self__ attributes
632 dself = obj.__repr__.__self__
632 dself = obj.__repr__.__self__
633 p.pretty(None if dself is obj else dself)
633 p.pretty(None if dself is obj else dself)
634 else:
634 else:
635 p.pretty(obj.__self__)
635 p.pretty(obj.__self__)
636 p.end_group(8, '>')
636 p.end_group(8, '>')
637
637
638
638
639 def _re_pattern_pprint(obj, p, cycle):
639 def _re_pattern_pprint(obj, p, cycle):
640 """The pprint function for regular expression patterns."""
640 """The pprint function for regular expression patterns."""
641 p.text('re.compile(')
641 p.text('re.compile(')
642 pattern = repr(obj.pattern)
642 pattern = repr(obj.pattern)
643 if pattern[:1] in 'uU':
643 if pattern[:1] in 'uU':
644 pattern = pattern[1:]
644 pattern = pattern[1:]
645 prefix = 'ur'
645 prefix = 'ur'
646 else:
646 else:
647 prefix = 'r'
647 prefix = 'r'
648 pattern = prefix + pattern.replace('\\\\', '\\')
648 pattern = prefix + pattern.replace('\\\\', '\\')
649 p.text(pattern)
649 p.text(pattern)
650 if obj.flags:
650 if obj.flags:
651 p.text(',')
651 p.text(',')
652 p.breakable()
652 p.breakable()
653 done_one = False
653 done_one = False
654 for flag in ('TEMPLATE', 'IGNORECASE', 'LOCALE', 'MULTILINE', 'DOTALL',
654 for flag in ('TEMPLATE', 'IGNORECASE', 'LOCALE', 'MULTILINE', 'DOTALL',
655 'UNICODE', 'VERBOSE', 'DEBUG'):
655 'UNICODE', 'VERBOSE', 'DEBUG'):
656 if obj.flags & getattr(re, flag):
656 if obj.flags & getattr(re, flag):
657 if done_one:
657 if done_one:
658 p.text('|')
658 p.text('|')
659 p.text('re.' + flag)
659 p.text('re.' + flag)
660 done_one = True
660 done_one = True
661 p.text(')')
661 p.text(')')
662
662
663
663
664 def _type_pprint(obj, p, cycle):
664 def _type_pprint(obj, p, cycle):
665 """The pprint for classes and types."""
665 """The pprint for classes and types."""
666 # Heap allocated types might not have the module attribute,
666 # Heap allocated types might not have the module attribute,
667 # and others may set it to None.
667 # and others may set it to None.
668
668
669 # Checks for a __repr__ override in the metaclass. Can't compare the
669 # Checks for a __repr__ override in the metaclass. Can't compare the
670 # type(obj).__repr__ directly because in PyPy the representation function
670 # type(obj).__repr__ directly because in PyPy the representation function
671 # inherited from type isn't the same type.__repr__
671 # inherited from type isn't the same type.__repr__
672 if [m for m in _get_mro(type(obj)) if "__repr__" in vars(m)][:1] != [type]:
672 if [m for m in _get_mro(type(obj)) if "__repr__" in vars(m)][:1] != [type]:
673 _repr_pprint(obj, p, cycle)
673 _repr_pprint(obj, p, cycle)
674 return
674 return
675
675
676 mod = _safe_getattr(obj, '__module__', None)
676 mod = _safe_getattr(obj, '__module__', None)
677 try:
677 try:
678 name = obj.__qualname__
678 name = obj.__qualname__
679 if not isinstance(name, str):
679 if not isinstance(name, str):
680 # This can happen if the type implements __qualname__ as a property
680 # This can happen if the type implements __qualname__ as a property
681 # or other descriptor in Python 2.
681 # or other descriptor in Python 2.
682 raise Exception("Try __name__")
682 raise Exception("Try __name__")
683 except Exception:
683 except Exception:
684 name = obj.__name__
684 name = obj.__name__
685 if not isinstance(name, str):
685 if not isinstance(name, str):
686 name = '<unknown type>'
686 name = '<unknown type>'
687
687
688 if mod in (None, '__builtin__', 'builtins', 'exceptions'):
688 if mod in (None, '__builtin__', 'builtins', 'exceptions'):
689 p.text(name)
689 p.text(name)
690 else:
690 else:
691 p.text(mod + '.' + name)
691 p.text(mod + '.' + name)
692
692
693
693
694 def _repr_pprint(obj, p, cycle):
694 def _repr_pprint(obj, p, cycle):
695 """A pprint that just redirects to the normal repr function."""
695 """A pprint that just redirects to the normal repr function."""
696 # Find newlines and replace them with p.break_()
696 # Find newlines and replace them with p.break_()
697 output = repr(obj)
697 output = repr(obj)
698 for idx,output_line in enumerate(output.splitlines()):
698 for idx,output_line in enumerate(output.splitlines()):
699 if idx:
699 if idx:
700 p.break_()
700 p.break_()
701 p.text(output_line)
701 p.text(output_line)
702
702
703
703
704 def _function_pprint(obj, p, cycle):
704 def _function_pprint(obj, p, cycle):
705 """Base pprint for all functions and builtin functions."""
705 """Base pprint for all functions and builtin functions."""
706 name = _safe_getattr(obj, '__qualname__', obj.__name__)
706 name = _safe_getattr(obj, '__qualname__', obj.__name__)
707 mod = obj.__module__
707 mod = obj.__module__
708 if mod and mod not in ('__builtin__', 'builtins', 'exceptions'):
708 if mod and mod not in ('__builtin__', 'builtins', 'exceptions'):
709 name = mod + '.' + name
709 name = mod + '.' + name
710 try:
710 try:
711 func_def = name + str(signature(obj))
711 func_def = name + str(signature(obj))
712 except ValueError:
712 except ValueError:
713 func_def = name
713 func_def = name
714 p.text('<function %s>' % func_def)
714 p.text('<function %s>' % func_def)
715
715
716
716
717 def _exception_pprint(obj, p, cycle):
717 def _exception_pprint(obj, p, cycle):
718 """Base pprint for all exceptions."""
718 """Base pprint for all exceptions."""
719 name = getattr(obj.__class__, '__qualname__', obj.__class__.__name__)
719 name = getattr(obj.__class__, '__qualname__', obj.__class__.__name__)
720 if obj.__class__.__module__ not in ('exceptions', 'builtins'):
720 if obj.__class__.__module__ not in ('exceptions', 'builtins'):
721 name = '%s.%s' % (obj.__class__.__module__, name)
721 name = '%s.%s' % (obj.__class__.__module__, name)
722 step = len(name) + 1
722 step = len(name) + 1
723 p.begin_group(step, name + '(')
723 p.begin_group(step, name + '(')
724 for idx, arg in enumerate(getattr(obj, 'args', ())):
724 for idx, arg in enumerate(getattr(obj, 'args', ())):
725 if idx:
725 if idx:
726 p.text(',')
726 p.text(',')
727 p.breakable()
727 p.breakable()
728 p.pretty(arg)
728 p.pretty(arg)
729 p.end_group(step, ')')
729 p.end_group(step, ')')
730
730
731
731
732 #: the exception base
732 #: the exception base
733 try:
733 try:
734 _exception_base = BaseException
734 _exception_base = BaseException
735 except NameError:
735 except NameError:
736 _exception_base = Exception
736 _exception_base = Exception
737
737
738
738
739 #: printers for builtin types
739 #: printers for builtin types
740 _type_pprinters = {
740 _type_pprinters = {
741 int: _repr_pprint,
741 int: _repr_pprint,
742 float: _repr_pprint,
742 float: _repr_pprint,
743 str: _repr_pprint,
743 str: _repr_pprint,
744 tuple: _seq_pprinter_factory('(', ')'),
744 tuple: _seq_pprinter_factory('(', ')'),
745 list: _seq_pprinter_factory('[', ']'),
745 list: _seq_pprinter_factory('[', ']'),
746 dict: _dict_pprinter_factory('{', '}'),
746 dict: _dict_pprinter_factory('{', '}'),
747 set: _set_pprinter_factory('{', '}'),
747 set: _set_pprinter_factory('{', '}'),
748 frozenset: _set_pprinter_factory('frozenset({', '})'),
748 frozenset: _set_pprinter_factory('frozenset({', '})'),
749 super: _super_pprint,
749 super: _super_pprint,
750 _re_pattern_type: _re_pattern_pprint,
750 _re_pattern_type: _re_pattern_pprint,
751 type: _type_pprint,
751 type: _type_pprint,
752 types.FunctionType: _function_pprint,
752 types.FunctionType: _function_pprint,
753 types.BuiltinFunctionType: _function_pprint,
753 types.BuiltinFunctionType: _function_pprint,
754 types.MethodType: _repr_pprint,
754 types.MethodType: _repr_pprint,
755 datetime.datetime: _repr_pprint,
755 datetime.datetime: _repr_pprint,
756 datetime.timedelta: _repr_pprint,
756 datetime.timedelta: _repr_pprint,
757 _exception_base: _exception_pprint
757 _exception_base: _exception_pprint
758 }
758 }
759
759
760 # render os.environ like a dict
760 # render os.environ like a dict
761 _env_type = type(os.environ)
761 _env_type = type(os.environ)
762 # future-proof in case os.environ becomes a plain dict?
762 # future-proof in case os.environ becomes a plain dict?
763 if _env_type is not dict:
763 if _env_type is not dict:
764 _type_pprinters[_env_type] = _dict_pprinter_factory('environ{', '}')
764 _type_pprinters[_env_type] = _dict_pprinter_factory('environ{', '}')
765
765
766 try:
766 try:
767 # In PyPy, types.DictProxyType is dict, setting the dictproxy printer
767 # In PyPy, types.DictProxyType is dict, setting the dictproxy printer
768 # using dict.setdefault avoids overwritting the dict printer
768 # using dict.setdefault avoids overwriting the dict printer
769 _type_pprinters.setdefault(types.DictProxyType,
769 _type_pprinters.setdefault(types.DictProxyType,
770 _dict_pprinter_factory('dict_proxy({', '})'))
770 _dict_pprinter_factory('dict_proxy({', '})'))
771 _type_pprinters[types.ClassType] = _type_pprint
771 _type_pprinters[types.ClassType] = _type_pprint
772 _type_pprinters[types.SliceType] = _repr_pprint
772 _type_pprinters[types.SliceType] = _repr_pprint
773 except AttributeError: # Python 3
773 except AttributeError: # Python 3
774 _type_pprinters[types.MappingProxyType] = \
774 _type_pprinters[types.MappingProxyType] = \
775 _dict_pprinter_factory('mappingproxy({', '})')
775 _dict_pprinter_factory('mappingproxy({', '})')
776 _type_pprinters[slice] = _repr_pprint
776 _type_pprinters[slice] = _repr_pprint
777
777
778 try:
778 try:
779 _type_pprinters[long] = _repr_pprint
779 _type_pprinters[long] = _repr_pprint
780 _type_pprinters[unicode] = _repr_pprint
780 _type_pprinters[unicode] = _repr_pprint
781 except NameError:
781 except NameError:
782 _type_pprinters[range] = _repr_pprint
782 _type_pprinters[range] = _repr_pprint
783 _type_pprinters[bytes] = _repr_pprint
783 _type_pprinters[bytes] = _repr_pprint
784
784
785 #: printers for types specified by name
785 #: printers for types specified by name
786 _deferred_type_pprinters = {
786 _deferred_type_pprinters = {
787 }
787 }
788
788
789 def for_type(typ, func):
789 def for_type(typ, func):
790 """
790 """
791 Add a pretty printer for a given type.
791 Add a pretty printer for a given type.
792 """
792 """
793 oldfunc = _type_pprinters.get(typ, None)
793 oldfunc = _type_pprinters.get(typ, None)
794 if func is not None:
794 if func is not None:
795 # To support easy restoration of old pprinters, we need to ignore Nones.
795 # To support easy restoration of old pprinters, we need to ignore Nones.
796 _type_pprinters[typ] = func
796 _type_pprinters[typ] = func
797 return oldfunc
797 return oldfunc
798
798
799 def for_type_by_name(type_module, type_name, func):
799 def for_type_by_name(type_module, type_name, func):
800 """
800 """
801 Add a pretty printer for a type specified by the module and name of a type
801 Add a pretty printer for a type specified by the module and name of a type
802 rather than the type object itself.
802 rather than the type object itself.
803 """
803 """
804 key = (type_module, type_name)
804 key = (type_module, type_name)
805 oldfunc = _deferred_type_pprinters.get(key, None)
805 oldfunc = _deferred_type_pprinters.get(key, None)
806 if func is not None:
806 if func is not None:
807 # To support easy restoration of old pprinters, we need to ignore Nones.
807 # To support easy restoration of old pprinters, we need to ignore Nones.
808 _deferred_type_pprinters[key] = func
808 _deferred_type_pprinters[key] = func
809 return oldfunc
809 return oldfunc
810
810
811
811
812 #: printers for the default singletons
812 #: printers for the default singletons
813 _singleton_pprinters = dict.fromkeys(map(id, [None, True, False, Ellipsis,
813 _singleton_pprinters = dict.fromkeys(map(id, [None, True, False, Ellipsis,
814 NotImplemented]), _repr_pprint)
814 NotImplemented]), _repr_pprint)
815
815
816
816
817 def _defaultdict_pprint(obj, p, cycle):
817 def _defaultdict_pprint(obj, p, cycle):
818 name = obj.__class__.__name__
818 name = obj.__class__.__name__
819 with p.group(len(name) + 1, name + '(', ')'):
819 with p.group(len(name) + 1, name + '(', ')'):
820 if cycle:
820 if cycle:
821 p.text('...')
821 p.text('...')
822 else:
822 else:
823 p.pretty(obj.default_factory)
823 p.pretty(obj.default_factory)
824 p.text(',')
824 p.text(',')
825 p.breakable()
825 p.breakable()
826 p.pretty(dict(obj))
826 p.pretty(dict(obj))
827
827
828 def _ordereddict_pprint(obj, p, cycle):
828 def _ordereddict_pprint(obj, p, cycle):
829 name = obj.__class__.__name__
829 name = obj.__class__.__name__
830 with p.group(len(name) + 1, name + '(', ')'):
830 with p.group(len(name) + 1, name + '(', ')'):
831 if cycle:
831 if cycle:
832 p.text('...')
832 p.text('...')
833 elif len(obj):
833 elif len(obj):
834 p.pretty(list(obj.items()))
834 p.pretty(list(obj.items()))
835
835
836 def _deque_pprint(obj, p, cycle):
836 def _deque_pprint(obj, p, cycle):
837 name = obj.__class__.__name__
837 name = obj.__class__.__name__
838 with p.group(len(name) + 1, name + '(', ')'):
838 with p.group(len(name) + 1, name + '(', ')'):
839 if cycle:
839 if cycle:
840 p.text('...')
840 p.text('...')
841 else:
841 else:
842 p.pretty(list(obj))
842 p.pretty(list(obj))
843
843
844
844
845 def _counter_pprint(obj, p, cycle):
845 def _counter_pprint(obj, p, cycle):
846 name = obj.__class__.__name__
846 name = obj.__class__.__name__
847 with p.group(len(name) + 1, name + '(', ')'):
847 with p.group(len(name) + 1, name + '(', ')'):
848 if cycle:
848 if cycle:
849 p.text('...')
849 p.text('...')
850 elif len(obj):
850 elif len(obj):
851 p.pretty(dict(obj))
851 p.pretty(dict(obj))
852
852
853 for_type_by_name('collections', 'defaultdict', _defaultdict_pprint)
853 for_type_by_name('collections', 'defaultdict', _defaultdict_pprint)
854 for_type_by_name('collections', 'OrderedDict', _ordereddict_pprint)
854 for_type_by_name('collections', 'OrderedDict', _ordereddict_pprint)
855 for_type_by_name('collections', 'deque', _deque_pprint)
855 for_type_by_name('collections', 'deque', _deque_pprint)
856 for_type_by_name('collections', 'Counter', _counter_pprint)
856 for_type_by_name('collections', 'Counter', _counter_pprint)
857
857
858 if __name__ == '__main__':
858 if __name__ == '__main__':
859 from random import randrange
859 from random import randrange
860 class Foo(object):
860 class Foo(object):
861 def __init__(self):
861 def __init__(self):
862 self.foo = 1
862 self.foo = 1
863 self.bar = re.compile(r'\s+')
863 self.bar = re.compile(r'\s+')
864 self.blub = dict.fromkeys(range(30), randrange(1, 40))
864 self.blub = dict.fromkeys(range(30), randrange(1, 40))
865 self.hehe = 23424.234234
865 self.hehe = 23424.234234
866 self.list = ["blub", "blah", self]
866 self.list = ["blub", "blah", self]
867
867
868 def get_foo(self):
868 def get_foo(self):
869 print("foo")
869 print("foo")
870
870
871 pprint(Foo(), verbose=True)
871 pprint(Foo(), verbose=True)
@@ -1,46 +1,46 b''
1 """Some simple tests for the plugin while running scripts.
1 """Some simple tests for the plugin while running scripts.
2 """
2 """
3 # Module imports
3 # Module imports
4 # Std lib
4 # Std lib
5 import inspect
5 import inspect
6
6
7 # Our own
7 # Our own
8
8
9 #-----------------------------------------------------------------------------
9 #-----------------------------------------------------------------------------
10 # Testing functions
10 # Testing functions
11
11
12 def test_trivial():
12 def test_trivial():
13 """A trivial passing test."""
13 """A trivial passing test."""
14 pass
14 pass
15
15
16 def doctest_run():
16 def doctest_run():
17 """Test running a trivial script.
17 """Test running a trivial script.
18
18
19 In [13]: run simplevars.py
19 In [13]: run simplevars.py
20 x is: 1
20 x is: 1
21 """
21 """
22
22
23 def doctest_runvars():
23 def doctest_runvars():
24 """Test that variables defined in scripts get loaded correcly via %run.
24 """Test that variables defined in scripts get loaded correclty via %run.
25
25
26 In [13]: run simplevars.py
26 In [13]: run simplevars.py
27 x is: 1
27 x is: 1
28
28
29 In [14]: x
29 In [14]: x
30 Out[14]: 1
30 Out[14]: 1
31 """
31 """
32
32
33 def doctest_ivars():
33 def doctest_ivars():
34 """Test that variables defined interactively are picked up.
34 """Test that variables defined interactively are picked up.
35 In [5]: zz=1
35 In [5]: zz=1
36
36
37 In [6]: zz
37 In [6]: zz
38 Out[6]: 1
38 Out[6]: 1
39 """
39 """
40
40
41 def doctest_refs():
41 def doctest_refs():
42 """DocTest reference holding issues when running scripts.
42 """DocTest reference holding issues when running scripts.
43
43
44 In [32]: run show_refs.py
44 In [32]: run show_refs.py
45 c referrers: [<... 'dict'>]
45 c referrers: [<... 'dict'>]
46 """
46 """
@@ -1,96 +1,95 b''
1 # encoding: utf-8
1 # encoding: utf-8
2 """
2 """
3 Utilities for working with stack frames.
3 Utilities for working with stack frames.
4 """
4 """
5
5
6 #-----------------------------------------------------------------------------
6 #-----------------------------------------------------------------------------
7 # Copyright (C) 2008-2011 The IPython Development Team
7 # Copyright (C) 2008-2011 The IPython Development Team
8 #
8 #
9 # Distributed under the terms of the BSD License. The full license is in
9 # Distributed under the terms of the BSD License. The full license is in
10 # the file COPYING, distributed as part of this software.
10 # the file COPYING, distributed as part of this software.
11 #-----------------------------------------------------------------------------
11 #-----------------------------------------------------------------------------
12
12
13 #-----------------------------------------------------------------------------
13 #-----------------------------------------------------------------------------
14 # Imports
14 # Imports
15 #-----------------------------------------------------------------------------
15 #-----------------------------------------------------------------------------
16
16
17 import sys
17 import sys
18 from IPython.utils import py3compat
18 from IPython.utils import py3compat
19
19
20 #-----------------------------------------------------------------------------
20 #-----------------------------------------------------------------------------
21 # Code
21 # Code
22 #-----------------------------------------------------------------------------
22 #-----------------------------------------------------------------------------
23
23
24 def extract_vars(*names,**kw):
24 def extract_vars(*names,**kw):
25 """Extract a set of variables by name from another frame.
25 """Extract a set of variables by name from another frame.
26
26
27 Parameters
27 Parameters
28 ----------
28 ----------
29 *names : str
29 *names : str
30 One or more variable names which will be extracted from the caller's
30 One or more variable names which will be extracted from the caller's
31 frame.
31 frame.
32
32
33 depth : integer, optional
33 depth : integer, optional
34 How many frames in the stack to walk when looking for your variables.
34 How many frames in the stack to walk when looking for your variables.
35 The default is 0, which will use the frame where the call was made.
35 The default is 0, which will use the frame where the call was made.
36
36
37
37
38 Examples
38 Examples
39 --------
39 --------
40 ::
40 ::
41
41
42 In [2]: def func(x):
42 In [2]: def func(x):
43 ...: y = 1
43 ...: y = 1
44 ...: print(sorted(extract_vars('x','y').items()))
44 ...: print(sorted(extract_vars('x','y').items()))
45 ...:
45 ...:
46
46
47 In [3]: func('hello')
47 In [3]: func('hello')
48 [('x', 'hello'), ('y', 1)]
48 [('x', 'hello'), ('y', 1)]
49 """
49 """
50
50
51 depth = kw.get('depth',0)
51 depth = kw.get('depth',0)
52
52
53 callerNS = sys._getframe(depth+1).f_locals
53 callerNS = sys._getframe(depth+1).f_locals
54 return dict((k,callerNS[k]) for k in names)
54 return dict((k,callerNS[k]) for k in names)
55
55
56
56
57 def extract_vars_above(*names):
57 def extract_vars_above(*names):
58 """Extract a set of variables by name from another frame.
58 """Extract a set of variables by name from another frame.
59
59
60 Similar to extractVars(), but with a specified depth of 1, so that names
60 Similar to extractVars(), but with a specified depth of 1, so that names
61 are exctracted exactly from above the caller.
61 are extracted exactly from above the caller.
62
62
63 This is simply a convenience function so that the very common case (for us)
63 This is simply a convenience function so that the very common case (for us)
64 of skipping exactly 1 frame doesn't have to construct a special dict for
64 of skipping exactly 1 frame doesn't have to construct a special dict for
65 keyword passing."""
65 keyword passing."""
66
66
67 callerNS = sys._getframe(2).f_locals
67 callerNS = sys._getframe(2).f_locals
68 return dict((k,callerNS[k]) for k in names)
68 return dict((k,callerNS[k]) for k in names)
69
69
70
70
71 def debugx(expr,pre_msg=''):
71 def debugx(expr,pre_msg=''):
72 """Print the value of an expression from the caller's frame.
72 """Print the value of an expression from the caller's frame.
73
73
74 Takes an expression, evaluates it in the caller's frame and prints both
74 Takes an expression, evaluates it in the caller's frame and prints both
75 the given expression and the resulting value (as well as a debug mark
75 the given expression and the resulting value (as well as a debug mark
76 indicating the name of the calling function. The input must be of a form
76 indicating the name of the calling function. The input must be of a form
77 suitable for eval().
77 suitable for eval().
78
78
79 An optional message can be passed, which will be prepended to the printed
79 An optional message can be passed, which will be prepended to the printed
80 expr->value pair."""
80 expr->value pair."""
81
81
82 cf = sys._getframe(1)
82 cf = sys._getframe(1)
83 print('[DBG:%s] %s%s -> %r' % (cf.f_code.co_name,pre_msg,expr,
83 print('[DBG:%s] %s%s -> %r' % (cf.f_code.co_name,pre_msg,expr,
84 eval(expr,cf.f_globals,cf.f_locals)))
84 eval(expr,cf.f_globals,cf.f_locals)))
85
85
86
86
87 # deactivate it by uncommenting the following line, which makes it a no-op
87 # deactivate it by uncommenting the following line, which makes it a no-op
88 #def debugx(expr,pre_msg=''): pass
88 #def debugx(expr,pre_msg=''): pass
89
89
90 def extract_module_locals(depth=0):
90 def extract_module_locals(depth=0):
91 """Returns (module, locals) of the function `depth` frames away from the caller"""
91 """Returns (module, locals) of the function `depth` frames away from the caller"""
92 f = sys._getframe(depth + 1)
92 f = sys._getframe(depth + 1)
93 global_ns = f.f_globals
93 global_ns = f.f_globals
94 module = sys.modules[global_ns['__name__']]
94 module = sys.modules[global_ns['__name__']]
95 return (module, f.f_locals)
95 return (module, f.f_locals)
96
@@ -1,124 +1,70 b''
1 """Utility functions for finding modules
1 """Utility functions for finding modules
2
2
3 Utility functions for finding modules on sys.path.
3 Utility functions for finding modules on sys.path.
4
4
5 `find_mod` finds named module on sys.path.
5 `find_module` returns a path to module or None, given certain conditions.
6
7 `get_init` helper function that finds __init__ file in a directory.
8
9 `find_module` variant of imp.find_module in std_lib that only returns
10 path to module and not an open file object as well.
11
12
13
6
14 """
7 """
15 #-----------------------------------------------------------------------------
8 #-----------------------------------------------------------------------------
16 # Copyright (c) 2011, the IPython Development Team.
9 # Copyright (c) 2011, the IPython Development Team.
17 #
10 #
18 # Distributed under the terms of the Modified BSD License.
11 # Distributed under the terms of the Modified BSD License.
19 #
12 #
20 # The full license is in the file COPYING.txt, distributed with this software.
13 # The full license is in the file COPYING.txt, distributed with this software.
21 #-----------------------------------------------------------------------------
14 #-----------------------------------------------------------------------------
22
15
23 #-----------------------------------------------------------------------------
16 #-----------------------------------------------------------------------------
24 # Imports
17 # Imports
25 #-----------------------------------------------------------------------------
18 #-----------------------------------------------------------------------------
26
19
27 # Stdlib imports
20 # Stdlib imports
28 import imp
21 import importlib
29 import os
22 import os
30
23
31 # Third-party imports
24 # Third-party imports
32
25
33 # Our own imports
26 # Our own imports
34
27
35
28
36 #-----------------------------------------------------------------------------
29 #-----------------------------------------------------------------------------
37 # Globals and constants
30 # Globals and constants
38 #-----------------------------------------------------------------------------
31 #-----------------------------------------------------------------------------
39
32
40 #-----------------------------------------------------------------------------
33 #-----------------------------------------------------------------------------
41 # Local utilities
34 # Local utilities
42 #-----------------------------------------------------------------------------
35 #-----------------------------------------------------------------------------
43
36
44 #-----------------------------------------------------------------------------
37 #-----------------------------------------------------------------------------
45 # Classes and functions
38 # Classes and functions
46 #-----------------------------------------------------------------------------
39 #-----------------------------------------------------------------------------
47 def find_module(name, path=None):
48 """imp.find_module variant that only return path of module.
49
50 The `imp.find_module` returns a filehandle that we are not interested in.
51 Also we ignore any bytecode files that `imp.find_module` finds.
52
53 Parameters
54 ----------
55 name : str
56 name of module to locate
57 path : list of str
58 list of paths to search for `name`. If path=None then search sys.path
59
40
60 Returns
41 def find_mod(module_name):
61 -------
62 filename : str
63 Return full path of module or None if module is missing or does not have
64 .py or .pyw extension
65 """
66 if name is None:
67 return None
68 try:
69 file, filename, _ = imp.find_module(name, path)
70 except ImportError:
71 return None
72 if file is None:
73 return filename
74 else:
75 file.close()
76 if os.path.splitext(filename)[1] in [".py", ".pyc"]:
77 return filename
78 else:
79 return None
80
81 def get_init(dirname):
82 """Get __init__ file path for module directory
83
84 Parameters
85 ----------
86 dirname : str
87 Find the __init__ file in directory `dirname`
88
89 Returns
90 -------
91 init_path : str
92 Path to __init__ file
93 """
42 """
94 fbase = os.path.join(dirname, "__init__")
43 Find module `module_name` on sys.path, and return the path to module `module_name`.
95 for ext in [".py", ".pyw"]:
96 fname = fbase + ext
97 if os.path.isfile(fname):
98 return fname
99
44
45 - If `module_name` refers to a module directory, then return path to __init__ file.
46 - If `module_name` is a directory without an __init__file, return None.
47 - If module is missing or does not have a `.py` or `.pyw` extension, return None.
48 - Note that we are not interested in running bytecode.
49 - Otherwise, return the fill path of the module.
100
50
101 def find_mod(module_name):
102 """Find module `module_name` on sys.path
103
104 Return the path to module `module_name`. If `module_name` refers to
105 a module directory then return path to __init__ file. Return full
106 path of module or None if module is missing or does not have .py or .pyw
107 extension. We are not interested in running bytecode.
108
109 Parameters
51 Parameters
110 ----------
52 ----------
111 module_name : str
53 module_name : str
112
54
113 Returns
55 Returns
114 -------
56 -------
115 modulepath : str
57 module_path : str
116 Path to module `module_name`.
58 Path to module `module_name`, its __init__.py, or None,
59 depending on above conditions.
117 """
60 """
118 parts = module_name.split(".")
61 loader = importlib.util.find_spec(module_name)
119 basepath = find_module(parts[0])
62 module_path = loader.origin
120 for submodname in parts[1:]:
63 if module_path is None:
121 basepath = find_module(submodname, [basepath])
64 return None
122 if basepath and os.path.isdir(basepath):
65 else:
123 basepath = get_init(basepath)
66 split_path = module_path.split(".")
124 return basepath
67 if split_path[1] in ["py", "pyw"]:
68 return module_path
69 else:
70 return None
@@ -1,438 +1,438 b''
1 # encoding: utf-8
1 # encoding: utf-8
2 """
2 """
3 Utilities for path handling.
3 Utilities for path handling.
4 """
4 """
5
5
6 # Copyright (c) IPython Development Team.
6 # Copyright (c) IPython Development Team.
7 # Distributed under the terms of the Modified BSD License.
7 # Distributed under the terms of the Modified BSD License.
8
8
9 import os
9 import os
10 import sys
10 import sys
11 import errno
11 import errno
12 import shutil
12 import shutil
13 import random
13 import random
14 import glob
14 import glob
15 from warnings import warn
15 from warnings import warn
16
16
17 from IPython.utils.process import system
17 from IPython.utils.process import system
18 from IPython.utils import py3compat
18 from IPython.utils import py3compat
19 from IPython.utils.decorators import undoc
19 from IPython.utils.decorators import undoc
20
20
21 #-----------------------------------------------------------------------------
21 #-----------------------------------------------------------------------------
22 # Code
22 # Code
23 #-----------------------------------------------------------------------------
23 #-----------------------------------------------------------------------------
24
24
25 fs_encoding = sys.getfilesystemencoding()
25 fs_encoding = sys.getfilesystemencoding()
26
26
27 def _writable_dir(path):
27 def _writable_dir(path):
28 """Whether `path` is a directory, to which the user has write access."""
28 """Whether `path` is a directory, to which the user has write access."""
29 return os.path.isdir(path) and os.access(path, os.W_OK)
29 return os.path.isdir(path) and os.access(path, os.W_OK)
30
30
31 if sys.platform == 'win32':
31 if sys.platform == 'win32':
32 def _get_long_path_name(path):
32 def _get_long_path_name(path):
33 """Get a long path name (expand ~) on Windows using ctypes.
33 """Get a long path name (expand ~) on Windows using ctypes.
34
34
35 Examples
35 Examples
36 --------
36 --------
37
37
38 >>> get_long_path_name('c:\\docume~1')
38 >>> get_long_path_name('c:\\docume~1')
39 'c:\\\\Documents and Settings'
39 'c:\\\\Documents and Settings'
40
40
41 """
41 """
42 try:
42 try:
43 import ctypes
43 import ctypes
44 except ImportError:
44 except ImportError:
45 raise ImportError('you need to have ctypes installed for this to work')
45 raise ImportError('you need to have ctypes installed for this to work')
46 _GetLongPathName = ctypes.windll.kernel32.GetLongPathNameW
46 _GetLongPathName = ctypes.windll.kernel32.GetLongPathNameW
47 _GetLongPathName.argtypes = [ctypes.c_wchar_p, ctypes.c_wchar_p,
47 _GetLongPathName.argtypes = [ctypes.c_wchar_p, ctypes.c_wchar_p,
48 ctypes.c_uint ]
48 ctypes.c_uint ]
49
49
50 buf = ctypes.create_unicode_buffer(260)
50 buf = ctypes.create_unicode_buffer(260)
51 rv = _GetLongPathName(path, buf, 260)
51 rv = _GetLongPathName(path, buf, 260)
52 if rv == 0 or rv > 260:
52 if rv == 0 or rv > 260:
53 return path
53 return path
54 else:
54 else:
55 return buf.value
55 return buf.value
56 else:
56 else:
57 def _get_long_path_name(path):
57 def _get_long_path_name(path):
58 """Dummy no-op."""
58 """Dummy no-op."""
59 return path
59 return path
60
60
61
61
62
62
63 def get_long_path_name(path):
63 def get_long_path_name(path):
64 """Expand a path into its long form.
64 """Expand a path into its long form.
65
65
66 On Windows this expands any ~ in the paths. On other platforms, it is
66 On Windows this expands any ~ in the paths. On other platforms, it is
67 a null operation.
67 a null operation.
68 """
68 """
69 return _get_long_path_name(path)
69 return _get_long_path_name(path)
70
70
71
71
72 def unquote_filename(name, win32=(sys.platform=='win32')):
72 def unquote_filename(name, win32=(sys.platform=='win32')):
73 """ On Windows, remove leading and trailing quotes from filenames.
73 """ On Windows, remove leading and trailing quotes from filenames.
74
74
75 This function has been deprecated and should not be used any more:
75 This function has been deprecated and should not be used any more:
76 unquoting is now taken care of by :func:`IPython.utils.process.arg_split`.
76 unquoting is now taken care of by :func:`IPython.utils.process.arg_split`.
77 """
77 """
78 warn("'unquote_filename' is deprecated since IPython 5.0 and should not "
78 warn("'unquote_filename' is deprecated since IPython 5.0 and should not "
79 "be used anymore", DeprecationWarning, stacklevel=2)
79 "be used anymore", DeprecationWarning, stacklevel=2)
80 if win32:
80 if win32:
81 if name.startswith(("'", '"')) and name.endswith(("'", '"')):
81 if name.startswith(("'", '"')) and name.endswith(("'", '"')):
82 name = name[1:-1]
82 name = name[1:-1]
83 return name
83 return name
84
84
85
85
86 def compress_user(path):
86 def compress_user(path):
87 """Reverse of :func:`os.path.expanduser`
87 """Reverse of :func:`os.path.expanduser`
88 """
88 """
89 home = os.path.expanduser('~')
89 home = os.path.expanduser('~')
90 if path.startswith(home):
90 if path.startswith(home):
91 path = "~" + path[len(home):]
91 path = "~" + path[len(home):]
92 return path
92 return path
93
93
94 def get_py_filename(name, force_win32=None):
94 def get_py_filename(name, force_win32=None):
95 """Return a valid python filename in the current directory.
95 """Return a valid python filename in the current directory.
96
96
97 If the given name is not a file, it adds '.py' and searches again.
97 If the given name is not a file, it adds '.py' and searches again.
98 Raises IOError with an informative message if the file isn't found.
98 Raises IOError with an informative message if the file isn't found.
99 """
99 """
100
100
101 name = os.path.expanduser(name)
101 name = os.path.expanduser(name)
102 if force_win32 is not None:
102 if force_win32 is not None:
103 warn("The 'force_win32' argument to 'get_py_filename' is deprecated "
103 warn("The 'force_win32' argument to 'get_py_filename' is deprecated "
104 "since IPython 5.0 and should not be used anymore",
104 "since IPython 5.0 and should not be used anymore",
105 DeprecationWarning, stacklevel=2)
105 DeprecationWarning, stacklevel=2)
106 if not os.path.isfile(name) and not name.endswith('.py'):
106 if not os.path.isfile(name) and not name.endswith('.py'):
107 name += '.py'
107 name += '.py'
108 if os.path.isfile(name):
108 if os.path.isfile(name):
109 return name
109 return name
110 else:
110 else:
111 raise IOError('File `%r` not found.' % name)
111 raise IOError('File `%r` not found.' % name)
112
112
113
113
114 def filefind(filename, path_dirs=None):
114 def filefind(filename, path_dirs=None):
115 """Find a file by looking through a sequence of paths.
115 """Find a file by looking through a sequence of paths.
116
116
117 This iterates through a sequence of paths looking for a file and returns
117 This iterates through a sequence of paths looking for a file and returns
118 the full, absolute path of the first occurrence of the file. If no set of
118 the full, absolute path of the first occurrence of the file. If no set of
119 path dirs is given, the filename is tested as is, after running through
119 path dirs is given, the filename is tested as is, after running through
120 :func:`expandvars` and :func:`expanduser`. Thus a simple call::
120 :func:`expandvars` and :func:`expanduser`. Thus a simple call::
121
121
122 filefind('myfile.txt')
122 filefind('myfile.txt')
123
123
124 will find the file in the current working dir, but::
124 will find the file in the current working dir, but::
125
125
126 filefind('~/myfile.txt')
126 filefind('~/myfile.txt')
127
127
128 Will find the file in the users home directory. This function does not
128 Will find the file in the users home directory. This function does not
129 automatically try any paths, such as the cwd or the user's home directory.
129 automatically try any paths, such as the cwd or the user's home directory.
130
130
131 Parameters
131 Parameters
132 ----------
132 ----------
133 filename : str
133 filename : str
134 The filename to look for.
134 The filename to look for.
135 path_dirs : str, None or sequence of str
135 path_dirs : str, None or sequence of str
136 The sequence of paths to look for the file in. If None, the filename
136 The sequence of paths to look for the file in. If None, the filename
137 need to be absolute or be in the cwd. If a string, the string is
137 need to be absolute or be in the cwd. If a string, the string is
138 put into a sequence and the searched. If a sequence, walk through
138 put into a sequence and the searched. If a sequence, walk through
139 each element and join with ``filename``, calling :func:`expandvars`
139 each element and join with ``filename``, calling :func:`expandvars`
140 and :func:`expanduser` before testing for existence.
140 and :func:`expanduser` before testing for existence.
141
141
142 Returns
142 Returns
143 -------
143 -------
144 Raises :exc:`IOError` or returns absolute path to file.
144 Raises :exc:`IOError` or returns absolute path to file.
145 """
145 """
146
146
147 # If paths are quoted, abspath gets confused, strip them...
147 # If paths are quoted, abspath gets confused, strip them...
148 filename = filename.strip('"').strip("'")
148 filename = filename.strip('"').strip("'")
149 # If the input is an absolute path, just check it exists
149 # If the input is an absolute path, just check it exists
150 if os.path.isabs(filename) and os.path.isfile(filename):
150 if os.path.isabs(filename) and os.path.isfile(filename):
151 return filename
151 return filename
152
152
153 if path_dirs is None:
153 if path_dirs is None:
154 path_dirs = ("",)
154 path_dirs = ("",)
155 elif isinstance(path_dirs, str):
155 elif isinstance(path_dirs, str):
156 path_dirs = (path_dirs,)
156 path_dirs = (path_dirs,)
157
157
158 for path in path_dirs:
158 for path in path_dirs:
159 if path == '.': path = os.getcwd()
159 if path == '.': path = os.getcwd()
160 testname = expand_path(os.path.join(path, filename))
160 testname = expand_path(os.path.join(path, filename))
161 if os.path.isfile(testname):
161 if os.path.isfile(testname):
162 return os.path.abspath(testname)
162 return os.path.abspath(testname)
163
163
164 raise IOError("File %r does not exist in any of the search paths: %r" %
164 raise IOError("File %r does not exist in any of the search paths: %r" %
165 (filename, path_dirs) )
165 (filename, path_dirs) )
166
166
167
167
168 class HomeDirError(Exception):
168 class HomeDirError(Exception):
169 pass
169 pass
170
170
171
171
172 def get_home_dir(require_writable=False):
172 def get_home_dir(require_writable=False):
173 """Return the 'home' directory, as a unicode string.
173 """Return the 'home' directory, as a unicode string.
174
174
175 Uses os.path.expanduser('~'), and checks for writability.
175 Uses os.path.expanduser('~'), and checks for writability.
176
176
177 See stdlib docs for how this is determined.
177 See stdlib docs for how this is determined.
178 $HOME is first priority on *ALL* platforms.
178 $HOME is first priority on *ALL* platforms.
179
179
180 Parameters
180 Parameters
181 ----------
181 ----------
182
182
183 require_writable : bool [default: False]
183 require_writable : bool [default: False]
184 if True:
184 if True:
185 guarantees the return value is a writable directory, otherwise
185 guarantees the return value is a writable directory, otherwise
186 raises HomeDirError
186 raises HomeDirError
187 if False:
187 if False:
188 The path is resolved, but it is not guaranteed to exist or be writable.
188 The path is resolved, but it is not guaranteed to exist or be writable.
189 """
189 """
190
190
191 homedir = os.path.expanduser('~')
191 homedir = os.path.expanduser('~')
192 # Next line will make things work even when /home/ is a symlink to
192 # Next line will make things work even when /home/ is a symlink to
193 # /usr/home as it is on FreeBSD, for example
193 # /usr/home as it is on FreeBSD, for example
194 homedir = os.path.realpath(homedir)
194 homedir = os.path.realpath(homedir)
195
195
196 if not _writable_dir(homedir) and os.name == 'nt':
196 if not _writable_dir(homedir) and os.name == 'nt':
197 # expanduser failed, use the registry to get the 'My Documents' folder.
197 # expanduser failed, use the registry to get the 'My Documents' folder.
198 try:
198 try:
199 try:
199 try:
200 import winreg as wreg # Py 3
200 import winreg as wreg # Py 3
201 except ImportError:
201 except ImportError:
202 import _winreg as wreg # Py 2
202 import _winreg as wreg # Py 2
203 key = wreg.OpenKey(
203 key = wreg.OpenKey(
204 wreg.HKEY_CURRENT_USER,
204 wreg.HKEY_CURRENT_USER,
205 "Software\Microsoft\Windows\CurrentVersion\Explorer\Shell Folders"
205 r"Software\Microsoft\Windows\CurrentVersion\Explorer\Shell Folders"
206 )
206 )
207 homedir = wreg.QueryValueEx(key,'Personal')[0]
207 homedir = wreg.QueryValueEx(key,'Personal')[0]
208 key.Close()
208 key.Close()
209 except:
209 except:
210 pass
210 pass
211
211
212 if (not require_writable) or _writable_dir(homedir):
212 if (not require_writable) or _writable_dir(homedir):
213 return py3compat.cast_unicode(homedir, fs_encoding)
213 return py3compat.cast_unicode(homedir, fs_encoding)
214 else:
214 else:
215 raise HomeDirError('%s is not a writable dir, '
215 raise HomeDirError('%s is not a writable dir, '
216 'set $HOME environment variable to override' % homedir)
216 'set $HOME environment variable to override' % homedir)
217
217
218 def get_xdg_dir():
218 def get_xdg_dir():
219 """Return the XDG_CONFIG_HOME, if it is defined and exists, else None.
219 """Return the XDG_CONFIG_HOME, if it is defined and exists, else None.
220
220
221 This is only for non-OS X posix (Linux,Unix,etc.) systems.
221 This is only for non-OS X posix (Linux,Unix,etc.) systems.
222 """
222 """
223
223
224 env = os.environ
224 env = os.environ
225
225
226 if os.name == 'posix' and sys.platform != 'darwin':
226 if os.name == 'posix' and sys.platform != 'darwin':
227 # Linux, Unix, AIX, etc.
227 # Linux, Unix, AIX, etc.
228 # use ~/.config if empty OR not set
228 # use ~/.config if empty OR not set
229 xdg = env.get("XDG_CONFIG_HOME", None) or os.path.join(get_home_dir(), '.config')
229 xdg = env.get("XDG_CONFIG_HOME", None) or os.path.join(get_home_dir(), '.config')
230 if xdg and _writable_dir(xdg):
230 if xdg and _writable_dir(xdg):
231 return py3compat.cast_unicode(xdg, fs_encoding)
231 return py3compat.cast_unicode(xdg, fs_encoding)
232
232
233 return None
233 return None
234
234
235
235
236 def get_xdg_cache_dir():
236 def get_xdg_cache_dir():
237 """Return the XDG_CACHE_HOME, if it is defined and exists, else None.
237 """Return the XDG_CACHE_HOME, if it is defined and exists, else None.
238
238
239 This is only for non-OS X posix (Linux,Unix,etc.) systems.
239 This is only for non-OS X posix (Linux,Unix,etc.) systems.
240 """
240 """
241
241
242 env = os.environ
242 env = os.environ
243
243
244 if os.name == 'posix' and sys.platform != 'darwin':
244 if os.name == 'posix' and sys.platform != 'darwin':
245 # Linux, Unix, AIX, etc.
245 # Linux, Unix, AIX, etc.
246 # use ~/.cache if empty OR not set
246 # use ~/.cache if empty OR not set
247 xdg = env.get("XDG_CACHE_HOME", None) or os.path.join(get_home_dir(), '.cache')
247 xdg = env.get("XDG_CACHE_HOME", None) or os.path.join(get_home_dir(), '.cache')
248 if xdg and _writable_dir(xdg):
248 if xdg and _writable_dir(xdg):
249 return py3compat.cast_unicode(xdg, fs_encoding)
249 return py3compat.cast_unicode(xdg, fs_encoding)
250
250
251 return None
251 return None
252
252
253
253
254 @undoc
254 @undoc
255 def get_ipython_dir():
255 def get_ipython_dir():
256 warn("get_ipython_dir has moved to the IPython.paths module since IPython 4.0.", stacklevel=2)
256 warn("get_ipython_dir has moved to the IPython.paths module since IPython 4.0.", stacklevel=2)
257 from IPython.paths import get_ipython_dir
257 from IPython.paths import get_ipython_dir
258 return get_ipython_dir()
258 return get_ipython_dir()
259
259
260 @undoc
260 @undoc
261 def get_ipython_cache_dir():
261 def get_ipython_cache_dir():
262 warn("get_ipython_cache_dir has moved to the IPython.paths module since IPython 4.0.", stacklevel=2)
262 warn("get_ipython_cache_dir has moved to the IPython.paths module since IPython 4.0.", stacklevel=2)
263 from IPython.paths import get_ipython_cache_dir
263 from IPython.paths import get_ipython_cache_dir
264 return get_ipython_cache_dir()
264 return get_ipython_cache_dir()
265
265
266 @undoc
266 @undoc
267 def get_ipython_package_dir():
267 def get_ipython_package_dir():
268 warn("get_ipython_package_dir has moved to the IPython.paths module since IPython 4.0.", stacklevel=2)
268 warn("get_ipython_package_dir has moved to the IPython.paths module since IPython 4.0.", stacklevel=2)
269 from IPython.paths import get_ipython_package_dir
269 from IPython.paths import get_ipython_package_dir
270 return get_ipython_package_dir()
270 return get_ipython_package_dir()
271
271
272 @undoc
272 @undoc
273 def get_ipython_module_path(module_str):
273 def get_ipython_module_path(module_str):
274 warn("get_ipython_module_path has moved to the IPython.paths module since IPython 4.0.", stacklevel=2)
274 warn("get_ipython_module_path has moved to the IPython.paths module since IPython 4.0.", stacklevel=2)
275 from IPython.paths import get_ipython_module_path
275 from IPython.paths import get_ipython_module_path
276 return get_ipython_module_path(module_str)
276 return get_ipython_module_path(module_str)
277
277
278 @undoc
278 @undoc
279 def locate_profile(profile='default'):
279 def locate_profile(profile='default'):
280 warn("locate_profile has moved to the IPython.paths module since IPython 4.0.", stacklevel=2)
280 warn("locate_profile has moved to the IPython.paths module since IPython 4.0.", stacklevel=2)
281 from IPython.paths import locate_profile
281 from IPython.paths import locate_profile
282 return locate_profile(profile=profile)
282 return locate_profile(profile=profile)
283
283
284 def expand_path(s):
284 def expand_path(s):
285 """Expand $VARS and ~names in a string, like a shell
285 """Expand $VARS and ~names in a string, like a shell
286
286
287 :Examples:
287 :Examples:
288
288
289 In [2]: os.environ['FOO']='test'
289 In [2]: os.environ['FOO']='test'
290
290
291 In [3]: expand_path('variable FOO is $FOO')
291 In [3]: expand_path('variable FOO is $FOO')
292 Out[3]: 'variable FOO is test'
292 Out[3]: 'variable FOO is test'
293 """
293 """
294 # This is a pretty subtle hack. When expand user is given a UNC path
294 # This is a pretty subtle hack. When expand user is given a UNC path
295 # on Windows (\\server\share$\%username%), os.path.expandvars, removes
295 # on Windows (\\server\share$\%username%), os.path.expandvars, removes
296 # the $ to get (\\server\share\%username%). I think it considered $
296 # the $ to get (\\server\share\%username%). I think it considered $
297 # alone an empty var. But, we need the $ to remains there (it indicates
297 # alone an empty var. But, we need the $ to remains there (it indicates
298 # a hidden share).
298 # a hidden share).
299 if os.name=='nt':
299 if os.name=='nt':
300 s = s.replace('$\\', 'IPYTHON_TEMP')
300 s = s.replace('$\\', 'IPYTHON_TEMP')
301 s = os.path.expandvars(os.path.expanduser(s))
301 s = os.path.expandvars(os.path.expanduser(s))
302 if os.name=='nt':
302 if os.name=='nt':
303 s = s.replace('IPYTHON_TEMP', '$\\')
303 s = s.replace('IPYTHON_TEMP', '$\\')
304 return s
304 return s
305
305
306
306
307 def unescape_glob(string):
307 def unescape_glob(string):
308 """Unescape glob pattern in `string`."""
308 """Unescape glob pattern in `string`."""
309 def unescape(s):
309 def unescape(s):
310 for pattern in '*[]!?':
310 for pattern in '*[]!?':
311 s = s.replace(r'\{0}'.format(pattern), pattern)
311 s = s.replace(r'\{0}'.format(pattern), pattern)
312 return s
312 return s
313 return '\\'.join(map(unescape, string.split('\\\\')))
313 return '\\'.join(map(unescape, string.split('\\\\')))
314
314
315
315
316 def shellglob(args):
316 def shellglob(args):
317 """
317 """
318 Do glob expansion for each element in `args` and return a flattened list.
318 Do glob expansion for each element in `args` and return a flattened list.
319
319
320 Unmatched glob pattern will remain as-is in the returned list.
320 Unmatched glob pattern will remain as-is in the returned list.
321
321
322 """
322 """
323 expanded = []
323 expanded = []
324 # Do not unescape backslash in Windows as it is interpreted as
324 # Do not unescape backslash in Windows as it is interpreted as
325 # path separator:
325 # path separator:
326 unescape = unescape_glob if sys.platform != 'win32' else lambda x: x
326 unescape = unescape_glob if sys.platform != 'win32' else lambda x: x
327 for a in args:
327 for a in args:
328 expanded.extend(glob.glob(a) or [unescape(a)])
328 expanded.extend(glob.glob(a) or [unescape(a)])
329 return expanded
329 return expanded
330
330
331
331
332 def target_outdated(target,deps):
332 def target_outdated(target,deps):
333 """Determine whether a target is out of date.
333 """Determine whether a target is out of date.
334
334
335 target_outdated(target,deps) -> 1/0
335 target_outdated(target,deps) -> 1/0
336
336
337 deps: list of filenames which MUST exist.
337 deps: list of filenames which MUST exist.
338 target: single filename which may or may not exist.
338 target: single filename which may or may not exist.
339
339
340 If target doesn't exist or is older than any file listed in deps, return
340 If target doesn't exist or is older than any file listed in deps, return
341 true, otherwise return false.
341 true, otherwise return false.
342 """
342 """
343 try:
343 try:
344 target_time = os.path.getmtime(target)
344 target_time = os.path.getmtime(target)
345 except os.error:
345 except os.error:
346 return 1
346 return 1
347 for dep in deps:
347 for dep in deps:
348 dep_time = os.path.getmtime(dep)
348 dep_time = os.path.getmtime(dep)
349 if dep_time > target_time:
349 if dep_time > target_time:
350 #print "For target",target,"Dep failed:",dep # dbg
350 #print "For target",target,"Dep failed:",dep # dbg
351 #print "times (dep,tar):",dep_time,target_time # dbg
351 #print "times (dep,tar):",dep_time,target_time # dbg
352 return 1
352 return 1
353 return 0
353 return 0
354
354
355
355
356 def target_update(target,deps,cmd):
356 def target_update(target,deps,cmd):
357 """Update a target with a given command given a list of dependencies.
357 """Update a target with a given command given a list of dependencies.
358
358
359 target_update(target,deps,cmd) -> runs cmd if target is outdated.
359 target_update(target,deps,cmd) -> runs cmd if target is outdated.
360
360
361 This is just a wrapper around target_outdated() which calls the given
361 This is just a wrapper around target_outdated() which calls the given
362 command if target is outdated."""
362 command if target is outdated."""
363
363
364 if target_outdated(target,deps):
364 if target_outdated(target,deps):
365 system(cmd)
365 system(cmd)
366
366
367
367
368 ENOLINK = 1998
368 ENOLINK = 1998
369
369
370 def link(src, dst):
370 def link(src, dst):
371 """Hard links ``src`` to ``dst``, returning 0 or errno.
371 """Hard links ``src`` to ``dst``, returning 0 or errno.
372
372
373 Note that the special errno ``ENOLINK`` will be returned if ``os.link`` isn't
373 Note that the special errno ``ENOLINK`` will be returned if ``os.link`` isn't
374 supported by the operating system.
374 supported by the operating system.
375 """
375 """
376
376
377 if not hasattr(os, "link"):
377 if not hasattr(os, "link"):
378 return ENOLINK
378 return ENOLINK
379 link_errno = 0
379 link_errno = 0
380 try:
380 try:
381 os.link(src, dst)
381 os.link(src, dst)
382 except OSError as e:
382 except OSError as e:
383 link_errno = e.errno
383 link_errno = e.errno
384 return link_errno
384 return link_errno
385
385
386
386
387 def link_or_copy(src, dst):
387 def link_or_copy(src, dst):
388 """Attempts to hardlink ``src`` to ``dst``, copying if the link fails.
388 """Attempts to hardlink ``src`` to ``dst``, copying if the link fails.
389
389
390 Attempts to maintain the semantics of ``shutil.copy``.
390 Attempts to maintain the semantics of ``shutil.copy``.
391
391
392 Because ``os.link`` does not overwrite files, a unique temporary file
392 Because ``os.link`` does not overwrite files, a unique temporary file
393 will be used if the target already exists, then that file will be moved
393 will be used if the target already exists, then that file will be moved
394 into place.
394 into place.
395 """
395 """
396
396
397 if os.path.isdir(dst):
397 if os.path.isdir(dst):
398 dst = os.path.join(dst, os.path.basename(src))
398 dst = os.path.join(dst, os.path.basename(src))
399
399
400 link_errno = link(src, dst)
400 link_errno = link(src, dst)
401 if link_errno == errno.EEXIST:
401 if link_errno == errno.EEXIST:
402 if os.stat(src).st_ino == os.stat(dst).st_ino:
402 if os.stat(src).st_ino == os.stat(dst).st_ino:
403 # dst is already a hard link to the correct file, so we don't need
403 # dst is already a hard link to the correct file, so we don't need
404 # to do anything else. If we try to link and rename the file
404 # to do anything else. If we try to link and rename the file
405 # anyway, we get duplicate files - see http://bugs.python.org/issue21876
405 # anyway, we get duplicate files - see http://bugs.python.org/issue21876
406 return
406 return
407
407
408 new_dst = dst + "-temp-%04X" %(random.randint(1, 16**4), )
408 new_dst = dst + "-temp-%04X" %(random.randint(1, 16**4), )
409 try:
409 try:
410 link_or_copy(src, new_dst)
410 link_or_copy(src, new_dst)
411 except:
411 except:
412 try:
412 try:
413 os.remove(new_dst)
413 os.remove(new_dst)
414 except OSError:
414 except OSError:
415 pass
415 pass
416 raise
416 raise
417 os.rename(new_dst, dst)
417 os.rename(new_dst, dst)
418 elif link_errno != 0:
418 elif link_errno != 0:
419 # Either link isn't supported, or the filesystem doesn't support
419 # Either link isn't supported, or the filesystem doesn't support
420 # linking, or 'src' and 'dst' are on different filesystems.
420 # linking, or 'src' and 'dst' are on different filesystems.
421 shutil.copy(src, dst)
421 shutil.copy(src, dst)
422
422
423 def ensure_dir_exists(path, mode=0o755):
423 def ensure_dir_exists(path, mode=0o755):
424 """ensure that a directory exists
424 """ensure that a directory exists
425
425
426 If it doesn't exist, try to create it and protect against a race condition
426 If it doesn't exist, try to create it and protect against a race condition
427 if another process is doing the same.
427 if another process is doing the same.
428
428
429 The default permissions are 755, which differ from os.makedirs default of 777.
429 The default permissions are 755, which differ from os.makedirs default of 777.
430 """
430 """
431 if not os.path.exists(path):
431 if not os.path.exists(path):
432 try:
432 try:
433 os.makedirs(path, mode=mode)
433 os.makedirs(path, mode=mode)
434 except OSError as e:
434 except OSError as e:
435 if e.errno != errno.EEXIST:
435 if e.errno != errno.EEXIST:
436 raise
436 raise
437 elif not os.path.isdir(path):
437 elif not os.path.isdir(path):
438 raise IOError("%r exists but is not a directory" % path)
438 raise IOError("%r exists but is not a directory" % path)
@@ -1,11 +1,12 b''
1 """DEPRECATED: Function signature objects for callables.
1 """DEPRECATED: Function signature objects for callables.
2
2
3 Use the standard library version if available, as it is more up to date.
3 Use the standard library version if available, as it is more up to date.
4 Fallback on backport otherwise.
4 Fallback on backport otherwise.
5 """
5 """
6
6
7 import warnings
7 import warnings
8 warnings.warn("{} backport for Python 2 is deprecated in IPython 6, which only supports Python 3".format(__name__),
8 warnings.warn("{} backport for Python 2 is deprecated in IPython 6, which only supports "
9 "Python 3. Import directly from standard library `inspect`".format(__name__),
9 DeprecationWarning, stacklevel=2)
10 DeprecationWarning, stacklevel=2)
10
11
11 from inspect import BoundArguments, Parameter, Signature, signature
12 from inspect import BoundArguments, Parameter, Signature, signature
@@ -1,127 +1,107 b''
1 # encoding: utf-8
1 # encoding: utf-8
2 """Tests for IPython.utils.module_paths.py"""
2 """Tests for IPython.utils.module_paths.py"""
3
3
4 #-----------------------------------------------------------------------------
4 #-----------------------------------------------------------------------------
5 # Copyright (C) 2008-2011 The IPython Development Team
5 # Copyright (C) 2008-2011 The IPython Development Team
6 #
6 #
7 # Distributed under the terms of the BSD License. The full license is in
7 # Distributed under the terms of the BSD License. The full license is in
8 # the file COPYING, distributed as part of this software.
8 # the file COPYING, distributed as part of this software.
9 #-----------------------------------------------------------------------------
9 #-----------------------------------------------------------------------------
10
10
11 #-----------------------------------------------------------------------------
11 #-----------------------------------------------------------------------------
12 # Imports
12 # Imports
13 #-----------------------------------------------------------------------------
13 #-----------------------------------------------------------------------------
14
14
15
15
16 import os
16 import os
17 import shutil
17 import shutil
18 import sys
18 import sys
19 import tempfile
19 import tempfile
20
20
21 from os.path import join, abspath, split
21 from os.path import join, abspath, split
22
22
23 from IPython.testing.tools import make_tempfile
23 from IPython.testing.tools import make_tempfile
24
24
25 import IPython.utils.module_paths as mp
25 import IPython.utils.module_paths as mp
26
26
27 import nose.tools as nt
27 import nose.tools as nt
28
28
29 env = os.environ
29 env = os.environ
30 TEST_FILE_PATH = split(abspath(__file__))[0]
30 TEST_FILE_PATH = split(abspath(__file__))[0]
31 TMP_TEST_DIR = tempfile.mkdtemp()
31 TMP_TEST_DIR = tempfile.mkdtemp()
32 #
32 #
33 # Setup/teardown functions/decorators
33 # Setup/teardown functions/decorators
34 #
34 #
35
35
36 old_syspath = sys.path
36 old_syspath = sys.path
37
37
38 def make_empty_file(fname):
38 def make_empty_file(fname):
39 f = open(fname, 'w')
39 f = open(fname, 'w')
40 f.close()
40 f.close()
41
41
42
42
43 def setup():
43 def setup():
44 """Setup testenvironment for the module:
44 """Setup testenvironment for the module:
45
45
46 """
46 """
47 # Do not mask exceptions here. In particular, catching WindowsError is a
47 # Do not mask exceptions here. In particular, catching WindowsError is a
48 # problem because that exception is only defined on Windows...
48 # problem because that exception is only defined on Windows...
49 os.makedirs(join(TMP_TEST_DIR, "xmod"))
49 os.makedirs(join(TMP_TEST_DIR, "xmod"))
50 os.makedirs(join(TMP_TEST_DIR, "nomod"))
50 os.makedirs(join(TMP_TEST_DIR, "nomod"))
51 make_empty_file(join(TMP_TEST_DIR, "xmod/__init__.py"))
51 make_empty_file(join(TMP_TEST_DIR, "xmod/__init__.py"))
52 make_empty_file(join(TMP_TEST_DIR, "xmod/sub.py"))
52 make_empty_file(join(TMP_TEST_DIR, "xmod/sub.py"))
53 make_empty_file(join(TMP_TEST_DIR, "pack.py"))
53 make_empty_file(join(TMP_TEST_DIR, "pack.py"))
54 make_empty_file(join(TMP_TEST_DIR, "packpyc.pyc"))
54 make_empty_file(join(TMP_TEST_DIR, "packpyc.pyc"))
55 sys.path = [TMP_TEST_DIR]
55 sys.path = [TMP_TEST_DIR]
56
56
57 def teardown():
57 def teardown():
58 """Teardown testenvironment for the module:
58 """Teardown testenvironment for the module:
59
59
60 - Remove tempdir
60 - Remove tempdir
61 - restore sys.path
61 - restore sys.path
62 """
62 """
63 # Note: we remove the parent test dir, which is the root of all test
63 # Note: we remove the parent test dir, which is the root of all test
64 # subdirs we may have created. Use shutil instead of os.removedirs, so
64 # subdirs we may have created. Use shutil instead of os.removedirs, so
65 # that non-empty directories are all recursively removed.
65 # that non-empty directories are all recursively removed.
66 shutil.rmtree(TMP_TEST_DIR)
66 shutil.rmtree(TMP_TEST_DIR)
67 sys.path = old_syspath
67 sys.path = old_syspath
68
68
69
70 def test_get_init_1():
71 """See if get_init can find __init__.py in this testdir"""
72 with make_tempfile(join(TMP_TEST_DIR, "__init__.py")):
73 assert mp.get_init(TMP_TEST_DIR)
74
75 def test_get_init_2():
76 """See if get_init can find __init__.pyw in this testdir"""
77 with make_tempfile(join(TMP_TEST_DIR, "__init__.pyw")):
78 assert mp.get_init(TMP_TEST_DIR)
79
80 def test_get_init_3():
81 """get_init can't find __init__.pyc in this testdir"""
82 with make_tempfile(join(TMP_TEST_DIR, "__init__.pyc")):
83 nt.assert_is_none(mp.get_init(TMP_TEST_DIR))
84
85 def test_get_init_4():
86 """get_init can't find __init__ in empty testdir"""
87 nt.assert_is_none(mp.get_init(TMP_TEST_DIR))
88
89
90 def test_find_mod_1():
69 def test_find_mod_1():
70 """
71 Search for a directory's file path.
72 Expected output: a path to that directory's __init__.py file.
73 """
91 modpath = join(TMP_TEST_DIR, "xmod", "__init__.py")
74 modpath = join(TMP_TEST_DIR, "xmod", "__init__.py")
92 nt.assert_equal(mp.find_mod("xmod"), modpath)
75 nt.assert_equal(mp.find_mod("xmod"), modpath)
93
76
94 def test_find_mod_2():
77 def test_find_mod_2():
78 """
79 Search for a directory's file path.
80 Expected output: a path to that directory's __init__.py file.
81 TODO: Confirm why this is a duplicate test.
82 """
95 modpath = join(TMP_TEST_DIR, "xmod", "__init__.py")
83 modpath = join(TMP_TEST_DIR, "xmod", "__init__.py")
96 nt.assert_equal(mp.find_mod("xmod"), modpath)
84 nt.assert_equal(mp.find_mod("xmod"), modpath)
97
85
98 def test_find_mod_3():
86 def test_find_mod_3():
87 """
88 Search for a directory + a filename without its .py extension
89 Expected output: full path with .py extension.
90 """
99 modpath = join(TMP_TEST_DIR, "xmod", "sub.py")
91 modpath = join(TMP_TEST_DIR, "xmod", "sub.py")
100 nt.assert_equal(mp.find_mod("xmod.sub"), modpath)
92 nt.assert_equal(mp.find_mod("xmod.sub"), modpath)
101
93
102 def test_find_mod_4():
94 def test_find_mod_4():
95 """
96 Search for a filename without its .py extension
97 Expected output: full path with .py extension
98 """
103 modpath = join(TMP_TEST_DIR, "pack.py")
99 modpath = join(TMP_TEST_DIR, "pack.py")
104 nt.assert_equal(mp.find_mod("pack"), modpath)
100 nt.assert_equal(mp.find_mod("pack"), modpath)
105
101
106 def test_find_mod_5():
102 def test_find_mod_5():
107 modpath = join(TMP_TEST_DIR, "packpyc.pyc")
103 """
108 nt.assert_equal(mp.find_mod("packpyc"), modpath)
104 Search for a filename with a .pyc extension
109
105 Expected output: TODO: do we exclude or include .pyc files?
110 def test_find_module_1():
106 """
111 modpath = join(TMP_TEST_DIR, "xmod")
107 nt.assert_equal(mp.find_mod("packpyc"), None)
112 nt.assert_equal(mp.find_module("xmod"), modpath)
113
114 def test_find_module_2():
115 """Testing sys.path that is empty"""
116 nt.assert_is_none(mp.find_module("xmod", []))
117
118 def test_find_module_3():
119 """Testing sys.path that is empty"""
120 nt.assert_is_none(mp.find_module(None, None))
121
122 def test_find_module_4():
123 """Testing sys.path that is empty"""
124 nt.assert_is_none(mp.find_module(None))
125
126 def test_find_module_5():
127 nt.assert_is_none(mp.find_module("xmod.nopack"))
@@ -1,772 +1,772 b''
1 # encoding: utf-8
1 # encoding: utf-8
2 """
2 """
3 Utilities for working with strings and text.
3 Utilities for working with strings and text.
4
4
5 Inheritance diagram:
5 Inheritance diagram:
6
6
7 .. inheritance-diagram:: IPython.utils.text
7 .. inheritance-diagram:: IPython.utils.text
8 :parts: 3
8 :parts: 3
9 """
9 """
10
10
11 import os
11 import os
12 import re
12 import re
13 import sys
13 import sys
14 import textwrap
14 import textwrap
15 from string import Formatter
15 from string import Formatter
16 from pathlib import Path
16 from pathlib import Path
17
17
18 from IPython.utils import py3compat
18 from IPython.utils import py3compat
19
19
20 # datetime.strftime date format for ipython
20 # datetime.strftime date format for ipython
21 if sys.platform == 'win32':
21 if sys.platform == 'win32':
22 date_format = "%B %d, %Y"
22 date_format = "%B %d, %Y"
23 else:
23 else:
24 date_format = "%B %-d, %Y"
24 date_format = "%B %-d, %Y"
25
25
26 class LSString(str):
26 class LSString(str):
27 """String derivative with a special access attributes.
27 """String derivative with a special access attributes.
28
28
29 These are normal strings, but with the special attributes:
29 These are normal strings, but with the special attributes:
30
30
31 .l (or .list) : value as list (split on newlines).
31 .l (or .list) : value as list (split on newlines).
32 .n (or .nlstr): original value (the string itself).
32 .n (or .nlstr): original value (the string itself).
33 .s (or .spstr): value as whitespace-separated string.
33 .s (or .spstr): value as whitespace-separated string.
34 .p (or .paths): list of path objects (requires path.py package)
34 .p (or .paths): list of path objects (requires path.py package)
35
35
36 Any values which require transformations are computed only once and
36 Any values which require transformations are computed only once and
37 cached.
37 cached.
38
38
39 Such strings are very useful to efficiently interact with the shell, which
39 Such strings are very useful to efficiently interact with the shell, which
40 typically only understands whitespace-separated options for commands."""
40 typically only understands whitespace-separated options for commands."""
41
41
42 def get_list(self):
42 def get_list(self):
43 try:
43 try:
44 return self.__list
44 return self.__list
45 except AttributeError:
45 except AttributeError:
46 self.__list = self.split('\n')
46 self.__list = self.split('\n')
47 return self.__list
47 return self.__list
48
48
49 l = list = property(get_list)
49 l = list = property(get_list)
50
50
51 def get_spstr(self):
51 def get_spstr(self):
52 try:
52 try:
53 return self.__spstr
53 return self.__spstr
54 except AttributeError:
54 except AttributeError:
55 self.__spstr = self.replace('\n',' ')
55 self.__spstr = self.replace('\n',' ')
56 return self.__spstr
56 return self.__spstr
57
57
58 s = spstr = property(get_spstr)
58 s = spstr = property(get_spstr)
59
59
60 def get_nlstr(self):
60 def get_nlstr(self):
61 return self
61 return self
62
62
63 n = nlstr = property(get_nlstr)
63 n = nlstr = property(get_nlstr)
64
64
65 def get_paths(self):
65 def get_paths(self):
66 try:
66 try:
67 return self.__paths
67 return self.__paths
68 except AttributeError:
68 except AttributeError:
69 self.__paths = [Path(p) for p in self.split('\n') if os.path.exists(p)]
69 self.__paths = [Path(p) for p in self.split('\n') if os.path.exists(p)]
70 return self.__paths
70 return self.__paths
71
71
72 p = paths = property(get_paths)
72 p = paths = property(get_paths)
73
73
74 # FIXME: We need to reimplement type specific displayhook and then add this
74 # FIXME: We need to reimplement type specific displayhook and then add this
75 # back as a custom printer. This should also be moved outside utils into the
75 # back as a custom printer. This should also be moved outside utils into the
76 # core.
76 # core.
77
77
78 # def print_lsstring(arg):
78 # def print_lsstring(arg):
79 # """ Prettier (non-repr-like) and more informative printer for LSString """
79 # """ Prettier (non-repr-like) and more informative printer for LSString """
80 # print "LSString (.p, .n, .l, .s available). Value:"
80 # print "LSString (.p, .n, .l, .s available). Value:"
81 # print arg
81 # print arg
82 #
82 #
83 #
83 #
84 # print_lsstring = result_display.when_type(LSString)(print_lsstring)
84 # print_lsstring = result_display.when_type(LSString)(print_lsstring)
85
85
86
86
87 class SList(list):
87 class SList(list):
88 """List derivative with a special access attributes.
88 """List derivative with a special access attributes.
89
89
90 These are normal lists, but with the special attributes:
90 These are normal lists, but with the special attributes:
91
91
92 * .l (or .list) : value as list (the list itself).
92 * .l (or .list) : value as list (the list itself).
93 * .n (or .nlstr): value as a string, joined on newlines.
93 * .n (or .nlstr): value as a string, joined on newlines.
94 * .s (or .spstr): value as a string, joined on spaces.
94 * .s (or .spstr): value as a string, joined on spaces.
95 * .p (or .paths): list of path objects (requires path.py package)
95 * .p (or .paths): list of path objects (requires path.py package)
96
96
97 Any values which require transformations are computed only once and
97 Any values which require transformations are computed only once and
98 cached."""
98 cached."""
99
99
100 def get_list(self):
100 def get_list(self):
101 return self
101 return self
102
102
103 l = list = property(get_list)
103 l = list = property(get_list)
104
104
105 def get_spstr(self):
105 def get_spstr(self):
106 try:
106 try:
107 return self.__spstr
107 return self.__spstr
108 except AttributeError:
108 except AttributeError:
109 self.__spstr = ' '.join(self)
109 self.__spstr = ' '.join(self)
110 return self.__spstr
110 return self.__spstr
111
111
112 s = spstr = property(get_spstr)
112 s = spstr = property(get_spstr)
113
113
114 def get_nlstr(self):
114 def get_nlstr(self):
115 try:
115 try:
116 return self.__nlstr
116 return self.__nlstr
117 except AttributeError:
117 except AttributeError:
118 self.__nlstr = '\n'.join(self)
118 self.__nlstr = '\n'.join(self)
119 return self.__nlstr
119 return self.__nlstr
120
120
121 n = nlstr = property(get_nlstr)
121 n = nlstr = property(get_nlstr)
122
122
123 def get_paths(self):
123 def get_paths(self):
124 try:
124 try:
125 return self.__paths
125 return self.__paths
126 except AttributeError:
126 except AttributeError:
127 self.__paths = [Path(p) for p in self if os.path.exists(p)]
127 self.__paths = [Path(p) for p in self if os.path.exists(p)]
128 return self.__paths
128 return self.__paths
129
129
130 p = paths = property(get_paths)
130 p = paths = property(get_paths)
131
131
132 def grep(self, pattern, prune = False, field = None):
132 def grep(self, pattern, prune = False, field = None):
133 """ Return all strings matching 'pattern' (a regex or callable)
133 """ Return all strings matching 'pattern' (a regex or callable)
134
134
135 This is case-insensitive. If prune is true, return all items
135 This is case-insensitive. If prune is true, return all items
136 NOT matching the pattern.
136 NOT matching the pattern.
137
137
138 If field is specified, the match must occur in the specified
138 If field is specified, the match must occur in the specified
139 whitespace-separated field.
139 whitespace-separated field.
140
140
141 Examples::
141 Examples::
142
142
143 a.grep( lambda x: x.startswith('C') )
143 a.grep( lambda x: x.startswith('C') )
144 a.grep('Cha.*log', prune=1)
144 a.grep('Cha.*log', prune=1)
145 a.grep('chm', field=-1)
145 a.grep('chm', field=-1)
146 """
146 """
147
147
148 def match_target(s):
148 def match_target(s):
149 if field is None:
149 if field is None:
150 return s
150 return s
151 parts = s.split()
151 parts = s.split()
152 try:
152 try:
153 tgt = parts[field]
153 tgt = parts[field]
154 return tgt
154 return tgt
155 except IndexError:
155 except IndexError:
156 return ""
156 return ""
157
157
158 if isinstance(pattern, str):
158 if isinstance(pattern, str):
159 pred = lambda x : re.search(pattern, x, re.IGNORECASE)
159 pred = lambda x : re.search(pattern, x, re.IGNORECASE)
160 else:
160 else:
161 pred = pattern
161 pred = pattern
162 if not prune:
162 if not prune:
163 return SList([el for el in self if pred(match_target(el))])
163 return SList([el for el in self if pred(match_target(el))])
164 else:
164 else:
165 return SList([el for el in self if not pred(match_target(el))])
165 return SList([el for el in self if not pred(match_target(el))])
166
166
167 def fields(self, *fields):
167 def fields(self, *fields):
168 """ Collect whitespace-separated fields from string list
168 """ Collect whitespace-separated fields from string list
169
169
170 Allows quick awk-like usage of string lists.
170 Allows quick awk-like usage of string lists.
171
171
172 Example data (in var a, created by 'a = !ls -l')::
172 Example data (in var a, created by 'a = !ls -l')::
173
173
174 -rwxrwxrwx 1 ville None 18 Dec 14 2006 ChangeLog
174 -rwxrwxrwx 1 ville None 18 Dec 14 2006 ChangeLog
175 drwxrwxrwx+ 6 ville None 0 Oct 24 18:05 IPython
175 drwxrwxrwx+ 6 ville None 0 Oct 24 18:05 IPython
176
176
177 * ``a.fields(0)`` is ``['-rwxrwxrwx', 'drwxrwxrwx+']``
177 * ``a.fields(0)`` is ``['-rwxrwxrwx', 'drwxrwxrwx+']``
178 * ``a.fields(1,0)`` is ``['1 -rwxrwxrwx', '6 drwxrwxrwx+']``
178 * ``a.fields(1,0)`` is ``['1 -rwxrwxrwx', '6 drwxrwxrwx+']``
179 (note the joining by space).
179 (note the joining by space).
180 * ``a.fields(-1)`` is ``['ChangeLog', 'IPython']``
180 * ``a.fields(-1)`` is ``['ChangeLog', 'IPython']``
181
181
182 IndexErrors are ignored.
182 IndexErrors are ignored.
183
183
184 Without args, fields() just split()'s the strings.
184 Without args, fields() just split()'s the strings.
185 """
185 """
186 if len(fields) == 0:
186 if len(fields) == 0:
187 return [el.split() for el in self]
187 return [el.split() for el in self]
188
188
189 res = SList()
189 res = SList()
190 for el in [f.split() for f in self]:
190 for el in [f.split() for f in self]:
191 lineparts = []
191 lineparts = []
192
192
193 for fd in fields:
193 for fd in fields:
194 try:
194 try:
195 lineparts.append(el[fd])
195 lineparts.append(el[fd])
196 except IndexError:
196 except IndexError:
197 pass
197 pass
198 if lineparts:
198 if lineparts:
199 res.append(" ".join(lineparts))
199 res.append(" ".join(lineparts))
200
200
201 return res
201 return res
202
202
203 def sort(self,field= None, nums = False):
203 def sort(self,field= None, nums = False):
204 """ sort by specified fields (see fields())
204 """ sort by specified fields (see fields())
205
205
206 Example::
206 Example::
207
207
208 a.sort(1, nums = True)
208 a.sort(1, nums = True)
209
209
210 Sorts a by second field, in numerical order (so that 21 > 3)
210 Sorts a by second field, in numerical order (so that 21 > 3)
211
211
212 """
212 """
213
213
214 #decorate, sort, undecorate
214 #decorate, sort, undecorate
215 if field is not None:
215 if field is not None:
216 dsu = [[SList([line]).fields(field), line] for line in self]
216 dsu = [[SList([line]).fields(field), line] for line in self]
217 else:
217 else:
218 dsu = [[line, line] for line in self]
218 dsu = [[line, line] for line in self]
219 if nums:
219 if nums:
220 for i in range(len(dsu)):
220 for i in range(len(dsu)):
221 numstr = "".join([ch for ch in dsu[i][0] if ch.isdigit()])
221 numstr = "".join([ch for ch in dsu[i][0] if ch.isdigit()])
222 try:
222 try:
223 n = int(numstr)
223 n = int(numstr)
224 except ValueError:
224 except ValueError:
225 n = 0
225 n = 0
226 dsu[i][0] = n
226 dsu[i][0] = n
227
227
228
228
229 dsu.sort()
229 dsu.sort()
230 return SList([t[1] for t in dsu])
230 return SList([t[1] for t in dsu])
231
231
232
232
233 # FIXME: We need to reimplement type specific displayhook and then add this
233 # FIXME: We need to reimplement type specific displayhook and then add this
234 # back as a custom printer. This should also be moved outside utils into the
234 # back as a custom printer. This should also be moved outside utils into the
235 # core.
235 # core.
236
236
237 # def print_slist(arg):
237 # def print_slist(arg):
238 # """ Prettier (non-repr-like) and more informative printer for SList """
238 # """ Prettier (non-repr-like) and more informative printer for SList """
239 # print "SList (.p, .n, .l, .s, .grep(), .fields(), sort() available):"
239 # print "SList (.p, .n, .l, .s, .grep(), .fields(), sort() available):"
240 # if hasattr(arg, 'hideonce') and arg.hideonce:
240 # if hasattr(arg, 'hideonce') and arg.hideonce:
241 # arg.hideonce = False
241 # arg.hideonce = False
242 # return
242 # return
243 #
243 #
244 # nlprint(arg) # This was a nested list printer, now removed.
244 # nlprint(arg) # This was a nested list printer, now removed.
245 #
245 #
246 # print_slist = result_display.when_type(SList)(print_slist)
246 # print_slist = result_display.when_type(SList)(print_slist)
247
247
248
248
249 def indent(instr,nspaces=4, ntabs=0, flatten=False):
249 def indent(instr,nspaces=4, ntabs=0, flatten=False):
250 """Indent a string a given number of spaces or tabstops.
250 """Indent a string a given number of spaces or tabstops.
251
251
252 indent(str,nspaces=4,ntabs=0) -> indent str by ntabs+nspaces.
252 indent(str,nspaces=4,ntabs=0) -> indent str by ntabs+nspaces.
253
253
254 Parameters
254 Parameters
255 ----------
255 ----------
256
256
257 instr : basestring
257 instr : basestring
258 The string to be indented.
258 The string to be indented.
259 nspaces : int (default: 4)
259 nspaces : int (default: 4)
260 The number of spaces to be indented.
260 The number of spaces to be indented.
261 ntabs : int (default: 0)
261 ntabs : int (default: 0)
262 The number of tabs to be indented.
262 The number of tabs to be indented.
263 flatten : bool (default: False)
263 flatten : bool (default: False)
264 Whether to scrub existing indentation. If True, all lines will be
264 Whether to scrub existing indentation. If True, all lines will be
265 aligned to the same indentation. If False, existing indentation will
265 aligned to the same indentation. If False, existing indentation will
266 be strictly increased.
266 be strictly increased.
267
267
268 Returns
268 Returns
269 -------
269 -------
270
270
271 str|unicode : string indented by ntabs and nspaces.
271 str|unicode : string indented by ntabs and nspaces.
272
272
273 """
273 """
274 if instr is None:
274 if instr is None:
275 return
275 return
276 ind = '\t'*ntabs+' '*nspaces
276 ind = '\t'*ntabs+' '*nspaces
277 if flatten:
277 if flatten:
278 pat = re.compile(r'^\s*', re.MULTILINE)
278 pat = re.compile(r'^\s*', re.MULTILINE)
279 else:
279 else:
280 pat = re.compile(r'^', re.MULTILINE)
280 pat = re.compile(r'^', re.MULTILINE)
281 outstr = re.sub(pat, ind, instr)
281 outstr = re.sub(pat, ind, instr)
282 if outstr.endswith(os.linesep+ind):
282 if outstr.endswith(os.linesep+ind):
283 return outstr[:-len(ind)]
283 return outstr[:-len(ind)]
284 else:
284 else:
285 return outstr
285 return outstr
286
286
287
287
288 def list_strings(arg):
288 def list_strings(arg):
289 """Always return a list of strings, given a string or list of strings
289 """Always return a list of strings, given a string or list of strings
290 as input.
290 as input.
291
291
292 Examples
292 Examples
293 --------
293 --------
294 ::
294 ::
295
295
296 In [7]: list_strings('A single string')
296 In [7]: list_strings('A single string')
297 Out[7]: ['A single string']
297 Out[7]: ['A single string']
298
298
299 In [8]: list_strings(['A single string in a list'])
299 In [8]: list_strings(['A single string in a list'])
300 Out[8]: ['A single string in a list']
300 Out[8]: ['A single string in a list']
301
301
302 In [9]: list_strings(['A','list','of','strings'])
302 In [9]: list_strings(['A','list','of','strings'])
303 Out[9]: ['A', 'list', 'of', 'strings']
303 Out[9]: ['A', 'list', 'of', 'strings']
304 """
304 """
305
305
306 if isinstance(arg, str):
306 if isinstance(arg, str):
307 return [arg]
307 return [arg]
308 else:
308 else:
309 return arg
309 return arg
310
310
311
311
312 def marquee(txt='',width=78,mark='*'):
312 def marquee(txt='',width=78,mark='*'):
313 """Return the input string centered in a 'marquee'.
313 """Return the input string centered in a 'marquee'.
314
314
315 Examples
315 Examples
316 --------
316 --------
317 ::
317 ::
318
318
319 In [16]: marquee('A test',40)
319 In [16]: marquee('A test',40)
320 Out[16]: '**************** A test ****************'
320 Out[16]: '**************** A test ****************'
321
321
322 In [17]: marquee('A test',40,'-')
322 In [17]: marquee('A test',40,'-')
323 Out[17]: '---------------- A test ----------------'
323 Out[17]: '---------------- A test ----------------'
324
324
325 In [18]: marquee('A test',40,' ')
325 In [18]: marquee('A test',40,' ')
326 Out[18]: ' A test '
326 Out[18]: ' A test '
327
327
328 """
328 """
329 if not txt:
329 if not txt:
330 return (mark*width)[:width]
330 return (mark*width)[:width]
331 nmark = (width-len(txt)-2)//len(mark)//2
331 nmark = (width-len(txt)-2)//len(mark)//2
332 if nmark < 0: nmark =0
332 if nmark < 0: nmark =0
333 marks = mark*nmark
333 marks = mark*nmark
334 return '%s %s %s' % (marks,txt,marks)
334 return '%s %s %s' % (marks,txt,marks)
335
335
336
336
337 ini_spaces_re = re.compile(r'^(\s+)')
337 ini_spaces_re = re.compile(r'^(\s+)')
338
338
339 def num_ini_spaces(strng):
339 def num_ini_spaces(strng):
340 """Return the number of initial spaces in a string"""
340 """Return the number of initial spaces in a string"""
341
341
342 ini_spaces = ini_spaces_re.match(strng)
342 ini_spaces = ini_spaces_re.match(strng)
343 if ini_spaces:
343 if ini_spaces:
344 return ini_spaces.end()
344 return ini_spaces.end()
345 else:
345 else:
346 return 0
346 return 0
347
347
348
348
349 def format_screen(strng):
349 def format_screen(strng):
350 """Format a string for screen printing.
350 """Format a string for screen printing.
351
351
352 This removes some latex-type format codes."""
352 This removes some latex-type format codes."""
353 # Paragraph continue
353 # Paragraph continue
354 par_re = re.compile(r'\\$',re.MULTILINE)
354 par_re = re.compile(r'\\$',re.MULTILINE)
355 strng = par_re.sub('',strng)
355 strng = par_re.sub('',strng)
356 return strng
356 return strng
357
357
358
358
359 def dedent(text):
359 def dedent(text):
360 """Equivalent of textwrap.dedent that ignores unindented first line.
360 """Equivalent of textwrap.dedent that ignores unindented first line.
361
361
362 This means it will still dedent strings like:
362 This means it will still dedent strings like:
363 '''foo
363 '''foo
364 is a bar
364 is a bar
365 '''
365 '''
366
366
367 For use in wrap_paragraphs.
367 For use in wrap_paragraphs.
368 """
368 """
369
369
370 if text.startswith('\n'):
370 if text.startswith('\n'):
371 # text starts with blank line, don't ignore the first line
371 # text starts with blank line, don't ignore the first line
372 return textwrap.dedent(text)
372 return textwrap.dedent(text)
373
373
374 # split first line
374 # split first line
375 splits = text.split('\n',1)
375 splits = text.split('\n',1)
376 if len(splits) == 1:
376 if len(splits) == 1:
377 # only one line
377 # only one line
378 return textwrap.dedent(text)
378 return textwrap.dedent(text)
379
379
380 first, rest = splits
380 first, rest = splits
381 # dedent everything but the first line
381 # dedent everything but the first line
382 rest = textwrap.dedent(rest)
382 rest = textwrap.dedent(rest)
383 return '\n'.join([first, rest])
383 return '\n'.join([first, rest])
384
384
385
385
386 def wrap_paragraphs(text, ncols=80):
386 def wrap_paragraphs(text, ncols=80):
387 """Wrap multiple paragraphs to fit a specified width.
387 """Wrap multiple paragraphs to fit a specified width.
388
388
389 This is equivalent to textwrap.wrap, but with support for multiple
389 This is equivalent to textwrap.wrap, but with support for multiple
390 paragraphs, as separated by empty lines.
390 paragraphs, as separated by empty lines.
391
391
392 Returns
392 Returns
393 -------
393 -------
394
394
395 list of complete paragraphs, wrapped to fill `ncols` columns.
395 list of complete paragraphs, wrapped to fill `ncols` columns.
396 """
396 """
397 paragraph_re = re.compile(r'\n(\s*\n)+', re.MULTILINE)
397 paragraph_re = re.compile(r'\n(\s*\n)+', re.MULTILINE)
398 text = dedent(text).strip()
398 text = dedent(text).strip()
399 paragraphs = paragraph_re.split(text)[::2] # every other entry is space
399 paragraphs = paragraph_re.split(text)[::2] # every other entry is space
400 out_ps = []
400 out_ps = []
401 indent_re = re.compile(r'\n\s+', re.MULTILINE)
401 indent_re = re.compile(r'\n\s+', re.MULTILINE)
402 for p in paragraphs:
402 for p in paragraphs:
403 # presume indentation that survives dedent is meaningful formatting,
403 # presume indentation that survives dedent is meaningful formatting,
404 # so don't fill unless text is flush.
404 # so don't fill unless text is flush.
405 if indent_re.search(p) is None:
405 if indent_re.search(p) is None:
406 # wrap paragraph
406 # wrap paragraph
407 p = textwrap.fill(p, ncols)
407 p = textwrap.fill(p, ncols)
408 out_ps.append(p)
408 out_ps.append(p)
409 return out_ps
409 return out_ps
410
410
411
411
412 def long_substr(data):
412 def long_substr(data):
413 """Return the longest common substring in a list of strings.
413 """Return the longest common substring in a list of strings.
414
414
415 Credit: http://stackoverflow.com/questions/2892931/longest-common-substring-from-more-than-two-strings-python
415 Credit: http://stackoverflow.com/questions/2892931/longest-common-substring-from-more-than-two-strings-python
416 """
416 """
417 substr = ''
417 substr = ''
418 if len(data) > 1 and len(data[0]) > 0:
418 if len(data) > 1 and len(data[0]) > 0:
419 for i in range(len(data[0])):
419 for i in range(len(data[0])):
420 for j in range(len(data[0])-i+1):
420 for j in range(len(data[0])-i+1):
421 if j > len(substr) and all(data[0][i:i+j] in x for x in data):
421 if j > len(substr) and all(data[0][i:i+j] in x for x in data):
422 substr = data[0][i:i+j]
422 substr = data[0][i:i+j]
423 elif len(data) == 1:
423 elif len(data) == 1:
424 substr = data[0]
424 substr = data[0]
425 return substr
425 return substr
426
426
427
427
428 def strip_email_quotes(text):
428 def strip_email_quotes(text):
429 """Strip leading email quotation characters ('>').
429 """Strip leading email quotation characters ('>').
430
430
431 Removes any combination of leading '>' interspersed with whitespace that
431 Removes any combination of leading '>' interspersed with whitespace that
432 appears *identically* in all lines of the input text.
432 appears *identically* in all lines of the input text.
433
433
434 Parameters
434 Parameters
435 ----------
435 ----------
436 text : str
436 text : str
437
437
438 Examples
438 Examples
439 --------
439 --------
440
440
441 Simple uses::
441 Simple uses::
442
442
443 In [2]: strip_email_quotes('> > text')
443 In [2]: strip_email_quotes('> > text')
444 Out[2]: 'text'
444 Out[2]: 'text'
445
445
446 In [3]: strip_email_quotes('> > text\\n> > more')
446 In [3]: strip_email_quotes('> > text\\n> > more')
447 Out[3]: 'text\\nmore'
447 Out[3]: 'text\\nmore'
448
448
449 Note how only the common prefix that appears in all lines is stripped::
449 Note how only the common prefix that appears in all lines is stripped::
450
450
451 In [4]: strip_email_quotes('> > text\\n> > more\\n> more...')
451 In [4]: strip_email_quotes('> > text\\n> > more\\n> more...')
452 Out[4]: '> text\\n> more\\nmore...'
452 Out[4]: '> text\\n> more\\nmore...'
453
453
454 So if any line has no quote marks ('>') , then none are stripped from any
454 So if any line has no quote marks ('>') , then none are stripped from any
455 of them ::
455 of them ::
456
456
457 In [5]: strip_email_quotes('> > text\\n> > more\\nlast different')
457 In [5]: strip_email_quotes('> > text\\n> > more\\nlast different')
458 Out[5]: '> > text\\n> > more\\nlast different'
458 Out[5]: '> > text\\n> > more\\nlast different'
459 """
459 """
460 lines = text.splitlines()
460 lines = text.splitlines()
461 matches = set()
461 matches = set()
462 for line in lines:
462 for line in lines:
463 prefix = re.match(r'^(\s*>[ >]*)', line)
463 prefix = re.match(r'^(\s*>[ >]*)', line)
464 if prefix:
464 if prefix:
465 matches.add(prefix.group(1))
465 matches.add(prefix.group(1))
466 else:
466 else:
467 break
467 break
468 else:
468 else:
469 prefix = long_substr(list(matches))
469 prefix = long_substr(list(matches))
470 if prefix:
470 if prefix:
471 strip = len(prefix)
471 strip = len(prefix)
472 text = '\n'.join([ ln[strip:] for ln in lines])
472 text = '\n'.join([ ln[strip:] for ln in lines])
473 return text
473 return text
474
474
475 def strip_ansi(source):
475 def strip_ansi(source):
476 """
476 """
477 Remove ansi escape codes from text.
477 Remove ansi escape codes from text.
478
478
479 Parameters
479 Parameters
480 ----------
480 ----------
481 source : str
481 source : str
482 Source to remove the ansi from
482 Source to remove the ansi from
483 """
483 """
484 return re.sub(r'\033\[(\d|;)+?m', '', source)
484 return re.sub(r'\033\[(\d|;)+?m', '', source)
485
485
486
486
487 class EvalFormatter(Formatter):
487 class EvalFormatter(Formatter):
488 """A String Formatter that allows evaluation of simple expressions.
488 """A String Formatter that allows evaluation of simple expressions.
489
489
490 Note that this version interprets a : as specifying a format string (as per
490 Note that this version interprets a : as specifying a format string (as per
491 standard string formatting), so if slicing is required, you must explicitly
491 standard string formatting), so if slicing is required, you must explicitly
492 create a slice.
492 create a slice.
493
493
494 This is to be used in templating cases, such as the parallel batch
494 This is to be used in templating cases, such as the parallel batch
495 script templates, where simple arithmetic on arguments is useful.
495 script templates, where simple arithmetic on arguments is useful.
496
496
497 Examples
497 Examples
498 --------
498 --------
499 ::
499 ::
500
500
501 In [1]: f = EvalFormatter()
501 In [1]: f = EvalFormatter()
502 In [2]: f.format('{n//4}', n=8)
502 In [2]: f.format('{n//4}', n=8)
503 Out[2]: '2'
503 Out[2]: '2'
504
504
505 In [3]: f.format("{greeting[slice(2,4)]}", greeting="Hello")
505 In [3]: f.format("{greeting[slice(2,4)]}", greeting="Hello")
506 Out[3]: 'll'
506 Out[3]: 'll'
507 """
507 """
508 def get_field(self, name, args, kwargs):
508 def get_field(self, name, args, kwargs):
509 v = eval(name, kwargs)
509 v = eval(name, kwargs)
510 return v, name
510 return v, name
511
511
512 #XXX: As of Python 3.4, the format string parsing no longer splits on a colon
512 #XXX: As of Python 3.4, the format string parsing no longer splits on a colon
513 # inside [], so EvalFormatter can handle slicing. Once we only support 3.4 and
513 # inside [], so EvalFormatter can handle slicing. Once we only support 3.4 and
514 # above, it should be possible to remove FullEvalFormatter.
514 # above, it should be possible to remove FullEvalFormatter.
515
515
516 class FullEvalFormatter(Formatter):
516 class FullEvalFormatter(Formatter):
517 """A String Formatter that allows evaluation of simple expressions.
517 """A String Formatter that allows evaluation of simple expressions.
518
518
519 Any time a format key is not found in the kwargs,
519 Any time a format key is not found in the kwargs,
520 it will be tried as an expression in the kwargs namespace.
520 it will be tried as an expression in the kwargs namespace.
521
521
522 Note that this version allows slicing using [1:2], so you cannot specify
522 Note that this version allows slicing using [1:2], so you cannot specify
523 a format string. Use :class:`EvalFormatter` to permit format strings.
523 a format string. Use :class:`EvalFormatter` to permit format strings.
524
524
525 Examples
525 Examples
526 --------
526 --------
527 ::
527 ::
528
528
529 In [1]: f = FullEvalFormatter()
529 In [1]: f = FullEvalFormatter()
530 In [2]: f.format('{n//4}', n=8)
530 In [2]: f.format('{n//4}', n=8)
531 Out[2]: '2'
531 Out[2]: '2'
532
532
533 In [3]: f.format('{list(range(5))[2:4]}')
533 In [3]: f.format('{list(range(5))[2:4]}')
534 Out[3]: '[2, 3]'
534 Out[3]: '[2, 3]'
535
535
536 In [4]: f.format('{3*2}')
536 In [4]: f.format('{3*2}')
537 Out[4]: '6'
537 Out[4]: '6'
538 """
538 """
539 # copied from Formatter._vformat with minor changes to allow eval
539 # copied from Formatter._vformat with minor changes to allow eval
540 # and replace the format_spec code with slicing
540 # and replace the format_spec code with slicing
541 def vformat(self, format_string, args, kwargs):
541 def vformat(self, format_string, args, kwargs):
542 result = []
542 result = []
543 for literal_text, field_name, format_spec, conversion in \
543 for literal_text, field_name, format_spec, conversion in \
544 self.parse(format_string):
544 self.parse(format_string):
545
545
546 # output the literal text
546 # output the literal text
547 if literal_text:
547 if literal_text:
548 result.append(literal_text)
548 result.append(literal_text)
549
549
550 # if there's a field, output it
550 # if there's a field, output it
551 if field_name is not None:
551 if field_name is not None:
552 # this is some markup, find the object and do
552 # this is some markup, find the object and do
553 # the formatting
553 # the formatting
554
554
555 if format_spec:
555 if format_spec:
556 # override format spec, to allow slicing:
556 # override format spec, to allow slicing:
557 field_name = ':'.join([field_name, format_spec])
557 field_name = ':'.join([field_name, format_spec])
558
558
559 # eval the contents of the field for the object
559 # eval the contents of the field for the object
560 # to be formatted
560 # to be formatted
561 obj = eval(field_name, kwargs)
561 obj = eval(field_name, kwargs)
562
562
563 # do any conversion on the resulting object
563 # do any conversion on the resulting object
564 obj = self.convert_field(obj, conversion)
564 obj = self.convert_field(obj, conversion)
565
565
566 # format the object and append to the result
566 # format the object and append to the result
567 result.append(self.format_field(obj, ''))
567 result.append(self.format_field(obj, ''))
568
568
569 return ''.join(py3compat.cast_unicode(s) for s in result)
569 return ''.join(py3compat.cast_unicode(s) for s in result)
570
570
571
571
572 class DollarFormatter(FullEvalFormatter):
572 class DollarFormatter(FullEvalFormatter):
573 """Formatter allowing Itpl style $foo replacement, for names and attribute
573 """Formatter allowing Itpl style $foo replacement, for names and attribute
574 access only. Standard {foo} replacement also works, and allows full
574 access only. Standard {foo} replacement also works, and allows full
575 evaluation of its arguments.
575 evaluation of its arguments.
576
576
577 Examples
577 Examples
578 --------
578 --------
579 ::
579 ::
580
580
581 In [1]: f = DollarFormatter()
581 In [1]: f = DollarFormatter()
582 In [2]: f.format('{n//4}', n=8)
582 In [2]: f.format('{n//4}', n=8)
583 Out[2]: '2'
583 Out[2]: '2'
584
584
585 In [3]: f.format('23 * 76 is $result', result=23*76)
585 In [3]: f.format('23 * 76 is $result', result=23*76)
586 Out[3]: '23 * 76 is 1748'
586 Out[3]: '23 * 76 is 1748'
587
587
588 In [4]: f.format('$a or {b}', a=1, b=2)
588 In [4]: f.format('$a or {b}', a=1, b=2)
589 Out[4]: '1 or 2'
589 Out[4]: '1 or 2'
590 """
590 """
591 _dollar_pattern_ignore_single_quote = re.compile("(.*?)\$(\$?[\w\.]+)(?=([^']*'[^']*')*[^']*$)")
591 _dollar_pattern_ignore_single_quote = re.compile(r"(.*?)\$(\$?[\w\.]+)(?=([^']*'[^']*')*[^']*$)")
592 def parse(self, fmt_string):
592 def parse(self, fmt_string):
593 for literal_txt, field_name, format_spec, conversion \
593 for literal_txt, field_name, format_spec, conversion \
594 in Formatter.parse(self, fmt_string):
594 in Formatter.parse(self, fmt_string):
595
595
596 # Find $foo patterns in the literal text.
596 # Find $foo patterns in the literal text.
597 continue_from = 0
597 continue_from = 0
598 txt = ""
598 txt = ""
599 for m in self._dollar_pattern_ignore_single_quote.finditer(literal_txt):
599 for m in self._dollar_pattern_ignore_single_quote.finditer(literal_txt):
600 new_txt, new_field = m.group(1,2)
600 new_txt, new_field = m.group(1,2)
601 # $$foo --> $foo
601 # $$foo --> $foo
602 if new_field.startswith("$"):
602 if new_field.startswith("$"):
603 txt += new_txt + new_field
603 txt += new_txt + new_field
604 else:
604 else:
605 yield (txt + new_txt, new_field, "", None)
605 yield (txt + new_txt, new_field, "", None)
606 txt = ""
606 txt = ""
607 continue_from = m.end()
607 continue_from = m.end()
608
608
609 # Re-yield the {foo} style pattern
609 # Re-yield the {foo} style pattern
610 yield (txt + literal_txt[continue_from:], field_name, format_spec, conversion)
610 yield (txt + literal_txt[continue_from:], field_name, format_spec, conversion)
611
611
612 #-----------------------------------------------------------------------------
612 #-----------------------------------------------------------------------------
613 # Utils to columnize a list of string
613 # Utils to columnize a list of string
614 #-----------------------------------------------------------------------------
614 #-----------------------------------------------------------------------------
615
615
616 def _col_chunks(l, max_rows, row_first=False):
616 def _col_chunks(l, max_rows, row_first=False):
617 """Yield successive max_rows-sized column chunks from l."""
617 """Yield successive max_rows-sized column chunks from l."""
618 if row_first:
618 if row_first:
619 ncols = (len(l) // max_rows) + (len(l) % max_rows > 0)
619 ncols = (len(l) // max_rows) + (len(l) % max_rows > 0)
620 for i in range(ncols):
620 for i in range(ncols):
621 yield [l[j] for j in range(i, len(l), ncols)]
621 yield [l[j] for j in range(i, len(l), ncols)]
622 else:
622 else:
623 for i in range(0, len(l), max_rows):
623 for i in range(0, len(l), max_rows):
624 yield l[i:(i + max_rows)]
624 yield l[i:(i + max_rows)]
625
625
626
626
627 def _find_optimal(rlist, row_first=False, separator_size=2, displaywidth=80):
627 def _find_optimal(rlist, row_first=False, separator_size=2, displaywidth=80):
628 """Calculate optimal info to columnize a list of string"""
628 """Calculate optimal info to columnize a list of string"""
629 for max_rows in range(1, len(rlist) + 1):
629 for max_rows in range(1, len(rlist) + 1):
630 col_widths = list(map(max, _col_chunks(rlist, max_rows, row_first)))
630 col_widths = list(map(max, _col_chunks(rlist, max_rows, row_first)))
631 sumlength = sum(col_widths)
631 sumlength = sum(col_widths)
632 ncols = len(col_widths)
632 ncols = len(col_widths)
633 if sumlength + separator_size * (ncols - 1) <= displaywidth:
633 if sumlength + separator_size * (ncols - 1) <= displaywidth:
634 break
634 break
635 return {'num_columns': ncols,
635 return {'num_columns': ncols,
636 'optimal_separator_width': (displaywidth - sumlength) // (ncols - 1) if (ncols - 1) else 0,
636 'optimal_separator_width': (displaywidth - sumlength) // (ncols - 1) if (ncols - 1) else 0,
637 'max_rows': max_rows,
637 'max_rows': max_rows,
638 'column_widths': col_widths
638 'column_widths': col_widths
639 }
639 }
640
640
641
641
642 def _get_or_default(mylist, i, default=None):
642 def _get_or_default(mylist, i, default=None):
643 """return list item number, or default if don't exist"""
643 """return list item number, or default if don't exist"""
644 if i >= len(mylist):
644 if i >= len(mylist):
645 return default
645 return default
646 else :
646 else :
647 return mylist[i]
647 return mylist[i]
648
648
649
649
650 def compute_item_matrix(items, row_first=False, empty=None, *args, **kwargs) :
650 def compute_item_matrix(items, row_first=False, empty=None, *args, **kwargs) :
651 """Returns a nested list, and info to columnize items
651 """Returns a nested list, and info to columnize items
652
652
653 Parameters
653 Parameters
654 ----------
654 ----------
655
655
656 items
656 items
657 list of strings to columize
657 list of strings to columize
658 row_first : (default False)
658 row_first : (default False)
659 Whether to compute columns for a row-first matrix instead of
659 Whether to compute columns for a row-first matrix instead of
660 column-first (default).
660 column-first (default).
661 empty : (default None)
661 empty : (default None)
662 default value to fill list if needed
662 default value to fill list if needed
663 separator_size : int (default=2)
663 separator_size : int (default=2)
664 How much characters will be used as a separation between each columns.
664 How much characters will be used as a separation between each columns.
665 displaywidth : int (default=80)
665 displaywidth : int (default=80)
666 The width of the area onto which the columns should enter
666 The width of the area onto which the columns should enter
667
667
668 Returns
668 Returns
669 -------
669 -------
670
670
671 strings_matrix
671 strings_matrix
672
672
673 nested list of string, the outer most list contains as many list as
673 nested list of string, the outer most list contains as many list as
674 rows, the innermost lists have each as many element as columns. If the
674 rows, the innermost lists have each as many element as columns. If the
675 total number of elements in `items` does not equal the product of
675 total number of elements in `items` does not equal the product of
676 rows*columns, the last element of some lists are filled with `None`.
676 rows*columns, the last element of some lists are filled with `None`.
677
677
678 dict_info
678 dict_info
679 some info to make columnize easier:
679 some info to make columnize easier:
680
680
681 num_columns
681 num_columns
682 number of columns
682 number of columns
683 max_rows
683 max_rows
684 maximum number of rows (final number may be less)
684 maximum number of rows (final number may be less)
685 column_widths
685 column_widths
686 list of with of each columns
686 list of with of each columns
687 optimal_separator_width
687 optimal_separator_width
688 best separator width between columns
688 best separator width between columns
689
689
690 Examples
690 Examples
691 --------
691 --------
692 ::
692 ::
693
693
694 In [1]: l = ['aaa','b','cc','d','eeeee','f','g','h','i','j','k','l']
694 In [1]: l = ['aaa','b','cc','d','eeeee','f','g','h','i','j','k','l']
695 In [2]: list, info = compute_item_matrix(l, displaywidth=12)
695 In [2]: list, info = compute_item_matrix(l, displaywidth=12)
696 In [3]: list
696 In [3]: list
697 Out[3]: [['aaa', 'f', 'k'], ['b', 'g', 'l'], ['cc', 'h', None], ['d', 'i', None], ['eeeee', 'j', None]]
697 Out[3]: [['aaa', 'f', 'k'], ['b', 'g', 'l'], ['cc', 'h', None], ['d', 'i', None], ['eeeee', 'j', None]]
698 In [4]: ideal = {'num_columns': 3, 'column_widths': [5, 1, 1], 'optimal_separator_width': 2, 'max_rows': 5}
698 In [4]: ideal = {'num_columns': 3, 'column_widths': [5, 1, 1], 'optimal_separator_width': 2, 'max_rows': 5}
699 In [5]: all((info[k] == ideal[k] for k in ideal.keys()))
699 In [5]: all((info[k] == ideal[k] for k in ideal.keys()))
700 Out[5]: True
700 Out[5]: True
701 """
701 """
702 info = _find_optimal(list(map(len, items)), row_first, *args, **kwargs)
702 info = _find_optimal(list(map(len, items)), row_first, *args, **kwargs)
703 nrow, ncol = info['max_rows'], info['num_columns']
703 nrow, ncol = info['max_rows'], info['num_columns']
704 if row_first:
704 if row_first:
705 return ([[_get_or_default(items, r * ncol + c, default=empty) for c in range(ncol)] for r in range(nrow)], info)
705 return ([[_get_or_default(items, r * ncol + c, default=empty) for c in range(ncol)] for r in range(nrow)], info)
706 else:
706 else:
707 return ([[_get_or_default(items, c * nrow + r, default=empty) for c in range(ncol)] for r in range(nrow)], info)
707 return ([[_get_or_default(items, c * nrow + r, default=empty) for c in range(ncol)] for r in range(nrow)], info)
708
708
709
709
710 def columnize(items, row_first=False, separator=' ', displaywidth=80, spread=False):
710 def columnize(items, row_first=False, separator=' ', displaywidth=80, spread=False):
711 """ Transform a list of strings into a single string with columns.
711 """ Transform a list of strings into a single string with columns.
712
712
713 Parameters
713 Parameters
714 ----------
714 ----------
715 items : sequence of strings
715 items : sequence of strings
716 The strings to process.
716 The strings to process.
717
717
718 row_first : (default False)
718 row_first : (default False)
719 Whether to compute columns for a row-first matrix instead of
719 Whether to compute columns for a row-first matrix instead of
720 column-first (default).
720 column-first (default).
721
721
722 separator : str, optional [default is two spaces]
722 separator : str, optional [default is two spaces]
723 The string that separates columns.
723 The string that separates columns.
724
724
725 displaywidth : int, optional [default is 80]
725 displaywidth : int, optional [default is 80]
726 Width of the display in number of characters.
726 Width of the display in number of characters.
727
727
728 Returns
728 Returns
729 -------
729 -------
730 The formatted string.
730 The formatted string.
731 """
731 """
732 if not items:
732 if not items:
733 return '\n'
733 return '\n'
734 matrix, info = compute_item_matrix(items, row_first=row_first, separator_size=len(separator), displaywidth=displaywidth)
734 matrix, info = compute_item_matrix(items, row_first=row_first, separator_size=len(separator), displaywidth=displaywidth)
735 if spread:
735 if spread:
736 separator = separator.ljust(int(info['optimal_separator_width']))
736 separator = separator.ljust(int(info['optimal_separator_width']))
737 fmatrix = [filter(None, x) for x in matrix]
737 fmatrix = [filter(None, x) for x in matrix]
738 sjoin = lambda x : separator.join([ y.ljust(w, ' ') for y, w in zip(x, info['column_widths'])])
738 sjoin = lambda x : separator.join([ y.ljust(w, ' ') for y, w in zip(x, info['column_widths'])])
739 return '\n'.join(map(sjoin, fmatrix))+'\n'
739 return '\n'.join(map(sjoin, fmatrix))+'\n'
740
740
741
741
742 def get_text_list(list_, last_sep=' and ', sep=", ", wrap_item_with=""):
742 def get_text_list(list_, last_sep=' and ', sep=", ", wrap_item_with=""):
743 """
743 """
744 Return a string with a natural enumeration of items
744 Return a string with a natural enumeration of items
745
745
746 >>> get_text_list(['a', 'b', 'c', 'd'])
746 >>> get_text_list(['a', 'b', 'c', 'd'])
747 'a, b, c and d'
747 'a, b, c and d'
748 >>> get_text_list(['a', 'b', 'c'], ' or ')
748 >>> get_text_list(['a', 'b', 'c'], ' or ')
749 'a, b or c'
749 'a, b or c'
750 >>> get_text_list(['a', 'b', 'c'], ', ')
750 >>> get_text_list(['a', 'b', 'c'], ', ')
751 'a, b, c'
751 'a, b, c'
752 >>> get_text_list(['a', 'b'], ' or ')
752 >>> get_text_list(['a', 'b'], ' or ')
753 'a or b'
753 'a or b'
754 >>> get_text_list(['a'])
754 >>> get_text_list(['a'])
755 'a'
755 'a'
756 >>> get_text_list([])
756 >>> get_text_list([])
757 ''
757 ''
758 >>> get_text_list(['a', 'b'], wrap_item_with="`")
758 >>> get_text_list(['a', 'b'], wrap_item_with="`")
759 '`a` and `b`'
759 '`a` and `b`'
760 >>> get_text_list(['a', 'b', 'c', 'd'], " = ", sep=" + ")
760 >>> get_text_list(['a', 'b', 'c', 'd'], " = ", sep=" + ")
761 'a + b + c = d'
761 'a + b + c = d'
762 """
762 """
763 if len(list_) == 0:
763 if len(list_) == 0:
764 return ''
764 return ''
765 if wrap_item_with:
765 if wrap_item_with:
766 list_ = ['%s%s%s' % (wrap_item_with, item, wrap_item_with) for
766 list_ = ['%s%s%s' % (wrap_item_with, item, wrap_item_with) for
767 item in list_]
767 item in list_]
768 if len(list_) == 1:
768 if len(list_) == 1:
769 return list_[0]
769 return list_[0]
770 return '%s%s%s' % (
770 return '%s%s%s' % (
771 sep.join(i for i in list_[:-1]),
771 sep.join(i for i in list_[:-1]),
772 last_sep, list_[-1])
772 last_sep, list_[-1])
@@ -1,111 +1,111 b''
1 .. image:: https://codecov.io/github/ipython/ipython/coverage.svg?branch=master
1 .. image:: https://codecov.io/github/ipython/ipython/coverage.svg?branch=master
2 :target: https://codecov.io/github/ipython/ipython?branch=master
2 :target: https://codecov.io/github/ipython/ipython?branch=master
3
3
4 .. image:: https://img.shields.io/pypi/v/IPython.svg
4 .. image:: https://img.shields.io/pypi/v/IPython.svg
5 :target: https://pypi.python.org/pypi/ipython
5 :target: https://pypi.python.org/pypi/ipython
6
6
7 .. image:: https://img.shields.io/travis/ipython/ipython.svg
7 .. image:: https://img.shields.io/travis/ipython/ipython.svg
8 :target: https://travis-ci.org/ipython/ipython
8 :target: https://travis-ci.org/ipython/ipython
9
9
10 .. image:: https://www.codetriage.com/ipython/ipython/badges/users.svg
10 .. image:: https://www.codetriage.com/ipython/ipython/badges/users.svg
11 :target: https://www.codetriage.com/ipython/ipython/
11 :target: https://www.codetriage.com/ipython/ipython/
12
12
13 ===========================================
13 ===========================================
14 IPython: Productive Interactive Computing
14 IPython: Productive Interactive Computing
15 ===========================================
15 ===========================================
16
16
17 Overview
17 Overview
18 ========
18 ========
19
19
20 Welcome to IPython. Our full documentation is available on `ipython.readthedocs.io
20 Welcome to IPython. Our full documentation is available on `ipython.readthedocs.io
21 <https://ipython.readthedocs.io/en/stable/>`_ and contains information on how to install, use and
21 <https://ipython.readthedocs.io/en/stable/>`_ and contains information on how to install, use and
22 contribute to the project.
22 contribute to the project.
23
23
24 **IPython versions and Python Support**
24 **IPython versions and Python Support**
25
25
26 **IPython 7.0** requires Python version 3.4 and above.
26 **IPython 7.0** requires Python version 3.4 and above.
27
27
28 **IPython 6.x** requires Python version 3.3 and above.
28 **IPython 6.x** requires Python version 3.3 and above.
29
29
30 **IPython 5.x LTS** is the compatible release for Python 2.7.
30 **IPython 5.x LTS** is the compatible release for Python 2.7.
31 If you require Python 2 support, you **must** use IPython 5.x LTS. Please
31 If you require Python 2 support, you **must** use IPython 5.x LTS. Please
32 update your project configurations and requirements as necessary.
32 update your project configurations and requirements as necessary.
33
33
34
34
35 The Notebook, Qt console and a number of other pieces are now parts of *Jupyter*.
35 The Notebook, Qt console and a number of other pieces are now parts of *Jupyter*.
36 See the `Jupyter installation docs <https://jupyter.readthedocs.io/en/latest/install.html>`__
36 See the `Jupyter installation docs <https://jupyter.readthedocs.io/en/latest/install.html>`__
37 if you want to use these.
37 if you want to use these.
38
38
39
39
40
40
41
41
42 Development and Instant running
42 Development and Instant running
43 ===============================
43 ===============================
44
44
45 You can find the latest version of the development documentation on `readthedocs
45 You can find the latest version of the development documentation on `readthedocs
46 <https://ipython.readthedocs.io/en/latest/>`_.
46 <https://ipython.readthedocs.io/en/latest/>`_.
47
47
48 You can run IPython from this directory without even installing it system-wide
48 You can run IPython from this directory without even installing it system-wide
49 by typing at the terminal::
49 by typing at the terminal::
50
50
51 $ python -m IPython
51 $ python -m IPython
52
52
53 Or see the `development installation docs
53 Or see the `development installation docs
54 <https://ipython.readthedocs.io/en/latest/install/install.html#installing-the-development-version>`_
54 <https://ipython.readthedocs.io/en/latest/install/install.html#installing-the-development-version>`_
55 for the latest revision on read the docs.
55 for the latest revision on read the docs.
56
56
57 Documentation and installation instructions for older version of IPython can be
57 Documentation and installation instructions for older version of IPython can be
58 found on the `IPython website <http://ipython.org/documentation.html>`_
58 found on the `IPython website <https://ipython.org/documentation.html>`_
59
59
60
60
61
61
62 IPython requires Python version 3 or above
62 IPython requires Python version 3 or above
63 ==========================================
63 ==========================================
64
64
65 Starting with version 6.0, IPython does not support Python 2.7, 3.0, 3.1, or
65 Starting with version 6.0, IPython does not support Python 2.7, 3.0, 3.1, or
66 3.2.
66 3.2.
67
67
68 For a version compatible with Python 2.7, please install the 5.x LTS Long Term
68 For a version compatible with Python 2.7, please install the 5.x LTS Long Term
69 Support version.
69 Support version.
70
70
71 If you are encountering this error message you are likely trying to install or
71 If you are encountering this error message you are likely trying to install or
72 use IPython from source. You need to checkout the remote 5.x branch. If you are
72 use IPython from source. You need to checkout the remote 5.x branch. If you are
73 using git the following should work::
73 using git the following should work::
74
74
75 $ git fetch origin
75 $ git fetch origin
76 $ git checkout 5.x
76 $ git checkout 5.x
77
77
78 If you encounter this error message with a regular install of IPython, then you
78 If you encounter this error message with a regular install of IPython, then you
79 likely need to update your package manager, for example if you are using `pip`
79 likely need to update your package manager, for example if you are using `pip`
80 check the version of pip with::
80 check the version of pip with::
81
81
82 $ pip --version
82 $ pip --version
83
83
84 You will need to update pip to the version 9.0.1 or greater. If you are not using
84 You will need to update pip to the version 9.0.1 or greater. If you are not using
85 pip, please inquiry with the maintainers of the package for your package
85 pip, please inquiry with the maintainers of the package for your package
86 manager.
86 manager.
87
87
88 For more information see one of our blog posts:
88 For more information see one of our blog posts:
89
89
90 http://blog.jupyter.org/2016/07/08/ipython-5-0-released/
90 https://blog.jupyter.org/2016/07/08/ipython-5-0-released/
91
91
92 As well as the following Pull-Request for discussion:
92 As well as the following Pull-Request for discussion:
93
93
94 https://github.com/ipython/ipython/pull/9900
94 https://github.com/ipython/ipython/pull/9900
95
95
96 This error does also occur if you are invoking ``setup.py`` directly – which you
96 This error does also occur if you are invoking ``setup.py`` directly – which you
97 should not – or are using ``easy_install`` If this is the case, use ``pip
97 should not – or are using ``easy_install`` If this is the case, use ``pip
98 install .`` (instead of ``setup.py install`` , and ``pip install -e .`` instead
98 install .`` (instead of ``setup.py install`` , and ``pip install -e .`` instead
99 of ``setup.py develop`` If you are depending on IPython as a dependency you may
99 of ``setup.py develop`` If you are depending on IPython as a dependency you may
100 also want to have a conditional dependency on IPython depending on the Python
100 also want to have a conditional dependency on IPython depending on the Python
101 version::
101 version::
102
102
103 install_req = ['ipython']
103 install_req = ['ipython']
104 if sys.version_info[0] < 3 and 'bdist_wheel' not in sys.argv:
104 if sys.version_info[0] < 3 and 'bdist_wheel' not in sys.argv:
105 install_req.remove('ipython')
105 install_req.remove('ipython')
106 install_req.append('ipython<6')
106 install_req.append('ipython<6')
107
107
108 setup(
108 setup(
109 ...
109 ...
110 install_requires=install_req
110 install_requires=install_req
111 )
111 )
1 NO CONTENT: modified file
NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
General Comments 0
You need to be logged in to leave comments. Login now