##// END OF EJS Templates
Cleanup and type annotate completer.py...
Matthias Bussonnier -
Show More
@@ -0,0 +1,4 b''
1 [mypy]
2 python_version = 3.6
3 ignore_missing_imports = True
4 follow_imports = silent
@@ -1,114 +1,116 b''
1 # http://travis-ci.org/#!/ipython/ipython
1 # http://travis-ci.org/#!/ipython/ipython
2 language: python
2 language: python
3 os: linux
3 os: linux
4
4
5 addons:
5 addons:
6 apt:
6 apt:
7 packages:
7 packages:
8 - graphviz
8 - graphviz
9
9
10 python:
10 python:
11 - 3.6
11 - 3.6
12
12
13 sudo: false
13 sudo: false
14
14
15 env:
15 env:
16 global:
16 global:
17 - PATH=$TRAVIS_BUILD_DIR/pandoc:$PATH
17 - PATH=$TRAVIS_BUILD_DIR/pandoc:$PATH
18
18
19 group: edge
19 group: edge
20
20
21 before_install:
21 before_install:
22 - |
22 - |
23 # install Python on macOS
23 # install Python on macOS
24 if [[ "$TRAVIS_OS_NAME" == "osx" ]]; then
24 if [[ "$TRAVIS_OS_NAME" == "osx" ]]; then
25 env | sort
25 env | sort
26 if ! which python$TRAVIS_PYTHON_VERSION; then
26 if ! which python$TRAVIS_PYTHON_VERSION; then
27 HOMEBREW_NO_AUTO_UPDATE=1 brew tap minrk/homebrew-python-frameworks
27 HOMEBREW_NO_AUTO_UPDATE=1 brew tap minrk/homebrew-python-frameworks
28 HOMEBREW_NO_AUTO_UPDATE=1 brew cask install python-framework-${TRAVIS_PYTHON_VERSION/./}
28 HOMEBREW_NO_AUTO_UPDATE=1 brew cask install python-framework-${TRAVIS_PYTHON_VERSION/./}
29 fi
29 fi
30 python3 -m pip install virtualenv
30 python3 -m pip install virtualenv
31 python3 -m virtualenv -p $(which python$TRAVIS_PYTHON_VERSION) ~/travis-env
31 python3 -m virtualenv -p $(which python$TRAVIS_PYTHON_VERSION) ~/travis-env
32 source ~/travis-env/bin/activate
32 source ~/travis-env/bin/activate
33 fi
33 fi
34 - python --version
34 - python --version
35
35
36 install:
36 install:
37 - pip install pip --upgrade
37 - pip install pip --upgrade
38 - pip install setuptools --upgrade
38 - pip install setuptools --upgrade
39 - pip install -e file://$PWD#egg=ipython[test] --upgrade
39 - pip install -e file://$PWD#egg=ipython[test] --upgrade
40 - pip install trio curio --upgrade --upgrade-strategy eager
40 - pip install trio curio --upgrade --upgrade-strategy eager
41 - pip install pytest 'matplotlib !=3.2.0' mypy
41 - pip install pytest 'matplotlib !=3.2.0' mypy
42 - pip install codecov check-manifest --upgrade
42 - pip install codecov check-manifest --upgrade
43 - pip install mypy
43
44
44 script:
45 script:
45 - check-manifest
46 - check-manifest
46 - |
47 - |
47 if [[ "$TRAVIS_PYTHON_VERSION" == "nightly" ]]; then
48 if [[ "$TRAVIS_PYTHON_VERSION" == "nightly" ]]; then
48 # on nightly fake parso known the grammar
49 # on nightly fake parso known the grammar
49 cp /home/travis/virtualenv/python3.8-dev/lib/python3.8/site-packages/parso/python/grammar37.txt /home/travis/virtualenv/python3.8-dev/lib/python3.8/site-packages/parso/python/grammar38.txt
50 cp /home/travis/virtualenv/python3.8-dev/lib/python3.8/site-packages/parso/python/grammar37.txt /home/travis/virtualenv/python3.8-dev/lib/python3.8/site-packages/parso/python/grammar38.txt
50 fi
51 fi
51 - cd /tmp && iptest --coverage xml && cd -
52 - cd /tmp && iptest --coverage xml && cd -
52 - pytest IPython
53 - pytest IPython
53 - mypy --ignore-missing-imports -m IPython.terminal.ptutils
54 - mypy IPython/terminal/ptutils.py
55 - mypy IPython/core/c*.py
54 # On the latest Python (on Linux) only, make sure that the docs build.
56 # On the latest Python (on Linux) only, make sure that the docs build.
55 - |
57 - |
56 if [[ "$TRAVIS_PYTHON_VERSION" == "3.7" ]] && [[ "$TRAVIS_OS_NAME" == "linux" ]]; then
58 if [[ "$TRAVIS_PYTHON_VERSION" == "3.7" ]] && [[ "$TRAVIS_OS_NAME" == "linux" ]]; then
57 pip install -r docs/requirements.txt
59 pip install -r docs/requirements.txt
58 python tools/fixup_whats_new_pr.py
60 python tools/fixup_whats_new_pr.py
59 make -C docs/ html SPHINXOPTS="-W"
61 make -C docs/ html SPHINXOPTS="-W"
60 fi
62 fi
61
63
62 after_success:
64 after_success:
63 - cp /tmp/ipy_coverage.xml ./
65 - cp /tmp/ipy_coverage.xml ./
64 - cp /tmp/.coverage ./
66 - cp /tmp/.coverage ./
65 - codecov
67 - codecov
66
68
67 matrix:
69 matrix:
68 include:
70 include:
69 - arch: amd64
71 - arch: amd64
70 python: "3.7"
72 python: "3.7"
71 dist: xenial
73 dist: xenial
72 sudo: true
74 sudo: true
73 - arch: amd64
75 - arch: amd64
74 python: "3.8"
76 python: "3.8"
75 dist: xenial
77 dist: xenial
76 sudo: true
78 sudo: true
77 - arch: amd64
79 - arch: amd64
78 python: "nightly"
80 python: "nightly"
79 dist: xenial
81 dist: xenial
80 sudo: true
82 sudo: true
81 - arch: arm64
83 - arch: arm64
82 python: "nightly"
84 python: "nightly"
83 dist: bionic
85 dist: bionic
84 env: ARM64=True
86 env: ARM64=True
85 sudo: true
87 sudo: true
86 - os: osx
88 - os: osx
87 language: generic
89 language: generic
88 python: 3.6
90 python: 3.6
89 env: TRAVIS_PYTHON_VERSION=3.6
91 env: TRAVIS_PYTHON_VERSION=3.6
90 - os: osx
92 - os: osx
91 language: generic
93 language: generic
92 python: 3.7
94 python: 3.7
93 env: TRAVIS_PYTHON_VERSION=3.7
95 env: TRAVIS_PYTHON_VERSION=3.7
94 allow_failures:
96 allow_failures:
95 - python: nightly
97 - python: nightly
96
98
97 before_deploy:
99 before_deploy:
98 - rm -rf dist/
100 - rm -rf dist/
99 - python setup.py sdist
101 - python setup.py sdist
100 - python setup.py bdist_wheel
102 - python setup.py bdist_wheel
101
103
102 deploy:
104 deploy:
103 provider: releases
105 provider: releases
104 api_key:
106 api_key:
105 secure: Y/Ae9tYs5aoBU8bDjN2YrwGG6tCbezj/h3Lcmtx8HQavSbBgXnhnZVRb2snOKD7auqnqjfT/7QMm4ZyKvaOEgyggGktKqEKYHC8KOZ7yp8I5/UMDtk6j9TnXpSqqBxPiud4MDV76SfRYEQiaDoG4tGGvSfPJ9KcNjKrNvSyyxns=
107 secure: Y/Ae9tYs5aoBU8bDjN2YrwGG6tCbezj/h3Lcmtx8HQavSbBgXnhnZVRb2snOKD7auqnqjfT/7QMm4ZyKvaOEgyggGktKqEKYHC8KOZ7yp8I5/UMDtk6j9TnXpSqqBxPiud4MDV76SfRYEQiaDoG4tGGvSfPJ9KcNjKrNvSyyxns=
106 file: dist/*
108 file: dist/*
107 file_glob: true
109 file_glob: true
108 skip_cleanup: true
110 skip_cleanup: true
109 on:
111 on:
110 repo: ipython/ipython
112 repo: ipython/ipython
111 all_branches: true # Backports are released from e.g. 5.x branch
113 all_branches: true # Backports are released from e.g. 5.x branch
112 tags: true
114 tags: true
113 python: 3.6 # Any version should work, but we only need one
115 python: 3.6 # Any version should work, but we only need one
114 condition: $TRAVIS_OS_NAME = "linux"
116 condition: $TRAVIS_OS_NAME = "linux"
@@ -1,2146 +1,2196 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. Jedi is an autocompletion and static analysis
70 inspecting multiple namespaces. Jedi is an autocompletion and static analysis
71 for Python. The APIs attached to this new mechanism is unstable and will
71 for Python. The APIs attached to this new mechanism is unstable and will
72 raise unless use in an :any:`provisionalcompleter` context manager.
72 raise unless use in an :any:`provisionalcompleter` context 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 if :any:`jedi` is crashing, or if current
87 to have extra logging information if :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 builtins as builtin_mod
113 import builtins as builtin_mod
114 import glob
114 import glob
115 import inspect
115 import inspect
116 import itertools
116 import itertools
117 import keyword
117 import keyword
118 import os
118 import os
119 import re
119 import re
120 import string
120 import string
121 import sys
121 import sys
122 import time
122 import time
123 import unicodedata
123 import unicodedata
124 import uuid
124 import uuid
125 import warnings
125 import warnings
126 from contextlib import contextmanager
126 from contextlib import contextmanager
127 from importlib import import_module
127 from importlib import import_module
128 from types import SimpleNamespace
128 from types import SimpleNamespace
129 from typing import Iterable, Iterator, List, Tuple
129 from typing import Iterable, Iterator, List, Tuple, Union, Any, Sequence, Dict, NamedTuple, Pattern, Optional
130
130
131 from IPython.core.error import TryNext
131 from IPython.core.error import TryNext
132 from IPython.core.inputtransformer2 import ESC_MAGIC
132 from IPython.core.inputtransformer2 import ESC_MAGIC
133 from IPython.core.latex_symbols import latex_symbols, reverse_latex_symbol
133 from IPython.core.latex_symbols import latex_symbols, reverse_latex_symbol
134 from IPython.core.oinspect import InspectColors
134 from IPython.core.oinspect import InspectColors
135 from IPython.utils import generics
135 from IPython.utils import generics
136 from IPython.utils.dir2 import dir2, get_real_method
136 from IPython.utils.dir2 import dir2, get_real_method
137 from IPython.utils.path import ensure_dir_exists
137 from IPython.utils.path import ensure_dir_exists
138 from IPython.utils.process import arg_split
138 from IPython.utils.process import arg_split
139 from traitlets import Bool, Enum, Int, List as ListTrait, Unicode, default, observe
139 from traitlets import Bool, Enum, Int, List as ListTrait, Unicode, default, observe
140 from traitlets.config.configurable import Configurable
140 from traitlets.config.configurable import Configurable
141
141
142 import __main__
142 import __main__
143
143
144 # skip module docstests
144 # skip module docstests
145 skip_doctest = True
145 skip_doctest = True
146
146
147 try:
147 try:
148 import jedi
148 import jedi
149 jedi.settings.case_insensitive_completion = False
149 jedi.settings.case_insensitive_completion = False
150 import jedi.api.helpers
150 import jedi.api.helpers
151 import jedi.api.classes
151 import jedi.api.classes
152 JEDI_INSTALLED = True
152 JEDI_INSTALLED = True
153 except ImportError:
153 except ImportError:
154 JEDI_INSTALLED = False
154 JEDI_INSTALLED = False
155 #-----------------------------------------------------------------------------
155 #-----------------------------------------------------------------------------
156 # Globals
156 # Globals
157 #-----------------------------------------------------------------------------
157 #-----------------------------------------------------------------------------
158
158
159 # Public API
159 # Public API
160 __all__ = ['Completer','IPCompleter']
160 __all__ = ['Completer','IPCompleter']
161
161
162 if sys.platform == 'win32':
162 if sys.platform == 'win32':
163 PROTECTABLES = ' '
163 PROTECTABLES = ' '
164 else:
164 else:
165 PROTECTABLES = ' ()[]{}?=\\|;:\'#*"^&'
165 PROTECTABLES = ' ()[]{}?=\\|;:\'#*"^&'
166
166
167 # Protect against returning an enormous number of completions which the frontend
167 # Protect against returning an enormous number of completions which the frontend
168 # may have trouble processing.
168 # may have trouble processing.
169 MATCHES_LIMIT = 500
169 MATCHES_LIMIT = 500
170
170
171 _deprecation_readline_sentinel = object()
171 _deprecation_readline_sentinel = object()
172
172
173
173
174 class ProvisionalCompleterWarning(FutureWarning):
174 class ProvisionalCompleterWarning(FutureWarning):
175 """
175 """
176 Exception raise by an experimental feature in this module.
176 Exception raise by an experimental feature in this module.
177
177
178 Wrap code in :any:`provisionalcompleter` context manager if you
178 Wrap code in :any:`provisionalcompleter` context manager if you
179 are certain you want to use an unstable feature.
179 are certain you want to use an unstable feature.
180 """
180 """
181 pass
181 pass
182
182
183 warnings.filterwarnings('error', category=ProvisionalCompleterWarning)
183 warnings.filterwarnings('error', category=ProvisionalCompleterWarning)
184
184
185 @contextmanager
185 @contextmanager
186 def provisionalcompleter(action='ignore'):
186 def provisionalcompleter(action='ignore'):
187 """
187 """
188
188
189
189
190 This context manager has to be used in any place where unstable completer
190 This context manager has to be used in any place where unstable completer
191 behavior and API may be called.
191 behavior and API may be called.
192
192
193 >>> with provisionalcompleter():
193 >>> with provisionalcompleter():
194 ... completer.do_experimental_things() # works
194 ... completer.do_experimental_things() # works
195
195
196 >>> completer.do_experimental_things() # raises.
196 >>> completer.do_experimental_things() # raises.
197
197
198 .. note:: Unstable
198 .. note:: Unstable
199
199
200 By using this context manager you agree that the API in use may change
200 By using this context manager you agree that the API in use may change
201 without warning, and that you won't complain if they do so.
201 without warning, and that you won't complain if they do so.
202
202
203 You also understand that, if the API is not to your liking, you should report
203 You also understand that, if the API is not to your liking, you should report
204 a bug to explain your use case upstream.
204 a bug to explain your use case upstream.
205
205
206 We'll be happy to get your feedback, feature requests, and improvements on
206 We'll be happy to get your feedback, feature requests, and improvements on
207 any of the unstable APIs!
207 any of the unstable APIs!
208 """
208 """
209 with warnings.catch_warnings():
209 with warnings.catch_warnings():
210 warnings.filterwarnings(action, category=ProvisionalCompleterWarning)
210 warnings.filterwarnings(action, category=ProvisionalCompleterWarning)
211 yield
211 yield
212
212
213
213
214 def has_open_quotes(s):
214 def has_open_quotes(s):
215 """Return whether a string has open quotes.
215 """Return whether a string has open quotes.
216
216
217 This simply counts whether the number of quote characters of either type in
217 This simply counts whether the number of quote characters of either type in
218 the string is odd.
218 the string is odd.
219
219
220 Returns
220 Returns
221 -------
221 -------
222 If there is an open quote, the quote character is returned. Else, return
222 If there is an open quote, the quote character is returned. Else, return
223 False.
223 False.
224 """
224 """
225 # We check " first, then ', so complex cases with nested quotes will get
225 # We check " first, then ', so complex cases with nested quotes will get
226 # the " to take precedence.
226 # the " to take precedence.
227 if s.count('"') % 2:
227 if s.count('"') % 2:
228 return '"'
228 return '"'
229 elif s.count("'") % 2:
229 elif s.count("'") % 2:
230 return "'"
230 return "'"
231 else:
231 else:
232 return False
232 return False
233
233
234
234
235 def protect_filename(s, protectables=PROTECTABLES):
235 def protect_filename(s, protectables=PROTECTABLES):
236 """Escape a string to protect certain characters."""
236 """Escape a string to protect certain characters."""
237 if set(s) & set(protectables):
237 if set(s) & set(protectables):
238 if sys.platform == "win32":
238 if sys.platform == "win32":
239 return '"' + s + '"'
239 return '"' + s + '"'
240 else:
240 else:
241 return "".join(("\\" + c if c in protectables else c) for c in s)
241 return "".join(("\\" + c if c in protectables else c) for c in s)
242 else:
242 else:
243 return s
243 return s
244
244
245
245
246 def expand_user(path:str) -> Tuple[str, bool, str]:
246 def expand_user(path:str) -> Tuple[str, bool, str]:
247 """Expand ``~``-style usernames in strings.
247 """Expand ``~``-style usernames in strings.
248
248
249 This is similar to :func:`os.path.expanduser`, but it computes and returns
249 This is similar to :func:`os.path.expanduser`, but it computes and returns
250 extra information that will be useful if the input was being used in
250 extra information that will be useful if the input was being used in
251 computing completions, and you wish to return the completions with the
251 computing completions, and you wish to return the completions with the
252 original '~' instead of its expanded value.
252 original '~' instead of its expanded value.
253
253
254 Parameters
254 Parameters
255 ----------
255 ----------
256 path : str
256 path : str
257 String to be expanded. If no ~ is present, the output is the same as the
257 String to be expanded. If no ~ is present, the output is the same as the
258 input.
258 input.
259
259
260 Returns
260 Returns
261 -------
261 -------
262 newpath : str
262 newpath : str
263 Result of ~ expansion in the input path.
263 Result of ~ expansion in the input path.
264 tilde_expand : bool
264 tilde_expand : bool
265 Whether any expansion was performed or not.
265 Whether any expansion was performed or not.
266 tilde_val : str
266 tilde_val : str
267 The value that ~ was replaced with.
267 The value that ~ was replaced with.
268 """
268 """
269 # Default values
269 # Default values
270 tilde_expand = False
270 tilde_expand = False
271 tilde_val = ''
271 tilde_val = ''
272 newpath = path
272 newpath = path
273
273
274 if path.startswith('~'):
274 if path.startswith('~'):
275 tilde_expand = True
275 tilde_expand = True
276 rest = len(path)-1
276 rest = len(path)-1
277 newpath = os.path.expanduser(path)
277 newpath = os.path.expanduser(path)
278 if rest:
278 if rest:
279 tilde_val = newpath[:-rest]
279 tilde_val = newpath[:-rest]
280 else:
280 else:
281 tilde_val = newpath
281 tilde_val = newpath
282
282
283 return newpath, tilde_expand, tilde_val
283 return newpath, tilde_expand, tilde_val
284
284
285
285
286 def compress_user(path:str, tilde_expand:bool, tilde_val:str) -> str:
286 def compress_user(path:str, tilde_expand:bool, tilde_val:str) -> str:
287 """Does the opposite of expand_user, with its outputs.
287 """Does the opposite of expand_user, with its outputs.
288 """
288 """
289 if tilde_expand:
289 if tilde_expand:
290 return path.replace(tilde_val, '~')
290 return path.replace(tilde_val, '~')
291 else:
291 else:
292 return path
292 return path
293
293
294
294
295 def completions_sorting_key(word):
295 def completions_sorting_key(word):
296 """key for sorting completions
296 """key for sorting completions
297
297
298 This does several things:
298 This does several things:
299
299
300 - Demote any completions starting with underscores to the end
300 - Demote any completions starting with underscores to the end
301 - Insert any %magic and %%cellmagic completions in the alphabetical order
301 - Insert any %magic and %%cellmagic completions in the alphabetical order
302 by their name
302 by their name
303 """
303 """
304 prio1, prio2 = 0, 0
304 prio1, prio2 = 0, 0
305
305
306 if word.startswith('__'):
306 if word.startswith('__'):
307 prio1 = 2
307 prio1 = 2
308 elif word.startswith('_'):
308 elif word.startswith('_'):
309 prio1 = 1
309 prio1 = 1
310
310
311 if word.endswith('='):
311 if word.endswith('='):
312 prio1 = -1
312 prio1 = -1
313
313
314 if word.startswith('%%'):
314 if word.startswith('%%'):
315 # If there's another % in there, this is something else, so leave it alone
315 # If there's another % in there, this is something else, so leave it alone
316 if not "%" in word[2:]:
316 if not "%" in word[2:]:
317 word = word[2:]
317 word = word[2:]
318 prio2 = 2
318 prio2 = 2
319 elif word.startswith('%'):
319 elif word.startswith('%'):
320 if not "%" in word[1:]:
320 if not "%" in word[1:]:
321 word = word[1:]
321 word = word[1:]
322 prio2 = 1
322 prio2 = 1
323
323
324 return prio1, word, prio2
324 return prio1, word, prio2
325
325
326
326
327 class _FakeJediCompletion:
327 class _FakeJediCompletion:
328 """
328 """
329 This is a workaround to communicate to the UI that Jedi has crashed and to
329 This is a workaround to communicate to the UI that Jedi has crashed and to
330 report a bug. Will be used only id :any:`IPCompleter.debug` is set to true.
330 report a bug. Will be used only id :any:`IPCompleter.debug` is set to true.
331
331
332 Added in IPython 6.0 so should likely be removed for 7.0
332 Added in IPython 6.0 so should likely be removed for 7.0
333
333
334 """
334 """
335
335
336 def __init__(self, name):
336 def __init__(self, name):
337
337
338 self.name = name
338 self.name = name
339 self.complete = name
339 self.complete = name
340 self.type = 'crashed'
340 self.type = 'crashed'
341 self.name_with_symbols = name
341 self.name_with_symbols = name
342 self.signature = ''
342 self.signature = ''
343 self._origin = 'fake'
343 self._origin = 'fake'
344
344
345 def __repr__(self):
345 def __repr__(self):
346 return '<Fake completion object jedi has crashed>'
346 return '<Fake completion object jedi has crashed>'
347
347
348
348
349 class Completion:
349 class Completion:
350 """
350 """
351 Completion object used and return by IPython completers.
351 Completion object used and return by IPython completers.
352
352
353 .. warning:: Unstable
353 .. warning:: Unstable
354
354
355 This function is unstable, API may change without warning.
355 This function is unstable, API may change without warning.
356 It will also raise unless use in proper context manager.
356 It will also raise unless use in proper context manager.
357
357
358 This act as a middle ground :any:`Completion` object between the
358 This act as a middle ground :any:`Completion` object between the
359 :any:`jedi.api.classes.Completion` object and the Prompt Toolkit completion
359 :any:`jedi.api.classes.Completion` object and the Prompt Toolkit completion
360 object. While Jedi need a lot of information about evaluator and how the
360 object. While Jedi need a lot of information about evaluator and how the
361 code should be ran/inspected, PromptToolkit (and other frontend) mostly
361 code should be ran/inspected, PromptToolkit (and other frontend) mostly
362 need user facing information.
362 need user facing information.
363
363
364 - Which range should be replaced replaced by what.
364 - Which range should be replaced replaced by what.
365 - Some metadata (like completion type), or meta information to displayed to
365 - Some metadata (like completion type), or meta information to displayed to
366 the use user.
366 the use user.
367
367
368 For debugging purpose we can also store the origin of the completion (``jedi``,
368 For debugging purpose we can also store the origin of the completion (``jedi``,
369 ``IPython.python_matches``, ``IPython.magics_matches``...).
369 ``IPython.python_matches``, ``IPython.magics_matches``...).
370 """
370 """
371
371
372 __slots__ = ['start', 'end', 'text', 'type', 'signature', '_origin']
372 __slots__ = ['start', 'end', 'text', 'type', 'signature', '_origin']
373
373
374 def __init__(self, start: int, end: int, text: str, *, type: str=None, _origin='', signature='') -> None:
374 def __init__(self, start: int, end: int, text: str, *, type: str=None, _origin='', signature='') -> None:
375 warnings.warn("``Completion`` is a provisional API (as of IPython 6.0). "
375 warnings.warn("``Completion`` is a provisional API (as of IPython 6.0). "
376 "It may change without warnings. "
376 "It may change without warnings. "
377 "Use in corresponding context manager.",
377 "Use in corresponding context manager.",
378 category=ProvisionalCompleterWarning, stacklevel=2)
378 category=ProvisionalCompleterWarning, stacklevel=2)
379
379
380 self.start = start
380 self.start = start
381 self.end = end
381 self.end = end
382 self.text = text
382 self.text = text
383 self.type = type
383 self.type = type
384 self.signature = signature
384 self.signature = signature
385 self._origin = _origin
385 self._origin = _origin
386
386
387 def __repr__(self):
387 def __repr__(self):
388 return '<Completion start=%s end=%s text=%r type=%r, signature=%r,>' % \
388 return '<Completion start=%s end=%s text=%r type=%r, signature=%r,>' % \
389 (self.start, self.end, self.text, self.type or '?', self.signature or '?')
389 (self.start, self.end, self.text, self.type or '?', self.signature or '?')
390
390
391 def __eq__(self, other)->Bool:
391 def __eq__(self, other)->Bool:
392 """
392 """
393 Equality and hash do not hash the type (as some completer may not be
393 Equality and hash do not hash the type (as some completer may not be
394 able to infer the type), but are use to (partially) de-duplicate
394 able to infer the type), but are use to (partially) de-duplicate
395 completion.
395 completion.
396
396
397 Completely de-duplicating completion is a bit tricker that just
397 Completely de-duplicating completion is a bit tricker that just
398 comparing as it depends on surrounding text, which Completions are not
398 comparing as it depends on surrounding text, which Completions are not
399 aware of.
399 aware of.
400 """
400 """
401 return self.start == other.start and \
401 return self.start == other.start and \
402 self.end == other.end and \
402 self.end == other.end and \
403 self.text == other.text
403 self.text == other.text
404
404
405 def __hash__(self):
405 def __hash__(self):
406 return hash((self.start, self.end, self.text))
406 return hash((self.start, self.end, self.text))
407
407
408
408
409 _IC = Iterable[Completion]
409 _IC = Iterable[Completion]
410
410
411
411
412 def _deduplicate_completions(text: str, completions: _IC)-> _IC:
412 def _deduplicate_completions(text: str, completions: _IC)-> _IC:
413 """
413 """
414 Deduplicate a set of completions.
414 Deduplicate a set of completions.
415
415
416 .. warning:: Unstable
416 .. warning:: Unstable
417
417
418 This function is unstable, API may change without warning.
418 This function is unstable, API may change without warning.
419
419
420 Parameters
420 Parameters
421 ----------
421 ----------
422 text: str
422 text: str
423 text that should be completed.
423 text that should be completed.
424 completions: Iterator[Completion]
424 completions: Iterator[Completion]
425 iterator over the completions to deduplicate
425 iterator over the completions to deduplicate
426
426
427 Yields
427 Yields
428 ------
428 ------
429 `Completions` objects
429 `Completions` objects
430
430
431
431
432 Completions coming from multiple sources, may be different but end up having
432 Completions coming from multiple sources, may be different but end up having
433 the same effect when applied to ``text``. If this is the case, this will
433 the same effect when applied to ``text``. If this is the case, this will
434 consider completions as equal and only emit the first encountered.
434 consider completions as equal and only emit the first encountered.
435
435
436 Not folded in `completions()` yet for debugging purpose, and to detect when
436 Not folded in `completions()` yet for debugging purpose, and to detect when
437 the IPython completer does return things that Jedi does not, but should be
437 the IPython completer does return things that Jedi does not, but should be
438 at some point.
438 at some point.
439 """
439 """
440 completions = list(completions)
440 completions = list(completions)
441 if not completions:
441 if not completions:
442 return
442 return
443
443
444 new_start = min(c.start for c in completions)
444 new_start = min(c.start for c in completions)
445 new_end = max(c.end for c in completions)
445 new_end = max(c.end for c in completions)
446
446
447 seen = set()
447 seen = set()
448 for c in completions:
448 for c in completions:
449 new_text = text[new_start:c.start] + c.text + text[c.end:new_end]
449 new_text = text[new_start:c.start] + c.text + text[c.end:new_end]
450 if new_text not in seen:
450 if new_text not in seen:
451 yield c
451 yield c
452 seen.add(new_text)
452 seen.add(new_text)
453
453
454
454
455 def rectify_completions(text: str, completions: _IC, *, _debug=False)->_IC:
455 def rectify_completions(text: str, completions: _IC, *, _debug=False)->_IC:
456 """
456 """
457 Rectify a set of completions to all have the same ``start`` and ``end``
457 Rectify a set of completions to all have the same ``start`` and ``end``
458
458
459 .. warning:: Unstable
459 .. warning:: Unstable
460
460
461 This function is unstable, API may change without warning.
461 This function is unstable, API may change without warning.
462 It will also raise unless use in proper context manager.
462 It will also raise unless use in proper context manager.
463
463
464 Parameters
464 Parameters
465 ----------
465 ----------
466 text: str
466 text: str
467 text that should be completed.
467 text that should be completed.
468 completions: Iterator[Completion]
468 completions: Iterator[Completion]
469 iterator over the completions to rectify
469 iterator over the completions to rectify
470
470
471
471
472 :any:`jedi.api.classes.Completion` s returned by Jedi may not have the same start and end, though
472 :any:`jedi.api.classes.Completion` s returned by Jedi may not have the same start and end, though
473 the Jupyter Protocol requires them to behave like so. This will readjust
473 the Jupyter Protocol requires them to behave like so. This will readjust
474 the completion to have the same ``start`` and ``end`` by padding both
474 the completion to have the same ``start`` and ``end`` by padding both
475 extremities with surrounding text.
475 extremities with surrounding text.
476
476
477 During stabilisation should support a ``_debug`` option to log which
477 During stabilisation should support a ``_debug`` option to log which
478 completion are return by the IPython completer and not found in Jedi in
478 completion are return by the IPython completer and not found in Jedi in
479 order to make upstream bug report.
479 order to make upstream bug report.
480 """
480 """
481 warnings.warn("`rectify_completions` is a provisional API (as of IPython 6.0). "
481 warnings.warn("`rectify_completions` is a provisional API (as of IPython 6.0). "
482 "It may change without warnings. "
482 "It may change without warnings. "
483 "Use in corresponding context manager.",
483 "Use in corresponding context manager.",
484 category=ProvisionalCompleterWarning, stacklevel=2)
484 category=ProvisionalCompleterWarning, stacklevel=2)
485
485
486 completions = list(completions)
486 completions = list(completions)
487 if not completions:
487 if not completions:
488 return
488 return
489 starts = (c.start for c in completions)
489 starts = (c.start for c in completions)
490 ends = (c.end for c in completions)
490 ends = (c.end for c in completions)
491
491
492 new_start = min(starts)
492 new_start = min(starts)
493 new_end = max(ends)
493 new_end = max(ends)
494
494
495 seen_jedi = set()
495 seen_jedi = set()
496 seen_python_matches = set()
496 seen_python_matches = set()
497 for c in completions:
497 for c in completions:
498 new_text = text[new_start:c.start] + c.text + text[c.end:new_end]
498 new_text = text[new_start:c.start] + c.text + text[c.end:new_end]
499 if c._origin == 'jedi':
499 if c._origin == 'jedi':
500 seen_jedi.add(new_text)
500 seen_jedi.add(new_text)
501 elif c._origin == 'IPCompleter.python_matches':
501 elif c._origin == 'IPCompleter.python_matches':
502 seen_python_matches.add(new_text)
502 seen_python_matches.add(new_text)
503 yield Completion(new_start, new_end, new_text, type=c.type, _origin=c._origin, signature=c.signature)
503 yield Completion(new_start, new_end, new_text, type=c.type, _origin=c._origin, signature=c.signature)
504 diff = seen_python_matches.difference(seen_jedi)
504 diff = seen_python_matches.difference(seen_jedi)
505 if diff and _debug:
505 if diff and _debug:
506 print('IPython.python matches have extras:', diff)
506 print('IPython.python matches have extras:', diff)
507
507
508
508
509 if sys.platform == 'win32':
509 if sys.platform == 'win32':
510 DELIMS = ' \t\n`!@#$^&*()=+[{]}|;\'",<>?'
510 DELIMS = ' \t\n`!@#$^&*()=+[{]}|;\'",<>?'
511 else:
511 else:
512 DELIMS = ' \t\n`!@#$^&*()=+[{]}\\|;:\'",<>?'
512 DELIMS = ' \t\n`!@#$^&*()=+[{]}\\|;:\'",<>?'
513
513
514 GREEDY_DELIMS = ' =\r\n'
514 GREEDY_DELIMS = ' =\r\n'
515
515
516
516
517 class CompletionSplitter(object):
517 class CompletionSplitter(object):
518 """An object to split an input line in a manner similar to readline.
518 """An object to split an input line in a manner similar to readline.
519
519
520 By having our own implementation, we can expose readline-like completion in
520 By having our own implementation, we can expose readline-like completion in
521 a uniform manner to all frontends. This object only needs to be given the
521 a uniform manner to all frontends. This object only needs to be given the
522 line of text to be split and the cursor position on said line, and it
522 line of text to be split and the cursor position on said line, and it
523 returns the 'word' to be completed on at the cursor after splitting the
523 returns the 'word' to be completed on at the cursor after splitting the
524 entire line.
524 entire line.
525
525
526 What characters are used as splitting delimiters can be controlled by
526 What characters are used as splitting delimiters can be controlled by
527 setting the ``delims`` attribute (this is a property that internally
527 setting the ``delims`` attribute (this is a property that internally
528 automatically builds the necessary regular expression)"""
528 automatically builds the necessary regular expression)"""
529
529
530 # Private interface
530 # Private interface
531
531
532 # A string of delimiter characters. The default value makes sense for
532 # A string of delimiter characters. The default value makes sense for
533 # IPython's most typical usage patterns.
533 # IPython's most typical usage patterns.
534 _delims = DELIMS
534 _delims = DELIMS
535
535
536 # The expression (a normal string) to be compiled into a regular expression
536 # The expression (a normal string) to be compiled into a regular expression
537 # for actual splitting. We store it as an attribute mostly for ease of
537 # for actual splitting. We store it as an attribute mostly for ease of
538 # debugging, since this type of code can be so tricky to debug.
538 # debugging, since this type of code can be so tricky to debug.
539 _delim_expr = None
539 _delim_expr = None
540
540
541 # The regular expression that does the actual splitting
541 # The regular expression that does the actual splitting
542 _delim_re = None
542 _delim_re = None
543
543
544 def __init__(self, delims=None):
544 def __init__(self, delims=None):
545 delims = CompletionSplitter._delims if delims is None else delims
545 delims = CompletionSplitter._delims if delims is None else delims
546 self.delims = delims
546 self.delims = delims
547
547
548 @property
548 @property
549 def delims(self):
549 def delims(self):
550 """Return the string of delimiter characters."""
550 """Return the string of delimiter characters."""
551 return self._delims
551 return self._delims
552
552
553 @delims.setter
553 @delims.setter
554 def delims(self, delims):
554 def delims(self, delims):
555 """Set the delimiters for line splitting."""
555 """Set the delimiters for line splitting."""
556 expr = '[' + ''.join('\\'+ c for c in delims) + ']'
556 expr = '[' + ''.join('\\'+ c for c in delims) + ']'
557 self._delim_re = re.compile(expr)
557 self._delim_re = re.compile(expr)
558 self._delims = delims
558 self._delims = delims
559 self._delim_expr = expr
559 self._delim_expr = expr
560
560
561 def split_line(self, line, cursor_pos=None):
561 def split_line(self, line, cursor_pos=None):
562 """Split a line of text with a cursor at the given position.
562 """Split a line of text with a cursor at the given position.
563 """
563 """
564 l = line if cursor_pos is None else line[:cursor_pos]
564 l = line if cursor_pos is None else line[:cursor_pos]
565 return self._delim_re.split(l)[-1]
565 return self._delim_re.split(l)[-1]
566
566
567
567
568
568
569 class Completer(Configurable):
569 class Completer(Configurable):
570
570
571 greedy = Bool(False,
571 greedy = Bool(False,
572 help="""Activate greedy completion
572 help="""Activate greedy completion
573 PENDING DEPRECTION. this is now mostly taken care of with Jedi.
573 PENDING DEPRECTION. this is now mostly taken care of with Jedi.
574
574
575 This will enable completion on elements of lists, results of function calls, etc.,
575 This will enable completion on elements of lists, results of function calls, etc.,
576 but can be unsafe because the code is actually evaluated on TAB.
576 but can be unsafe because the code is actually evaluated on TAB.
577 """
577 """
578 ).tag(config=True)
578 ).tag(config=True)
579
579
580 use_jedi = Bool(default_value=JEDI_INSTALLED,
580 use_jedi = Bool(default_value=JEDI_INSTALLED,
581 help="Experimental: Use Jedi to generate autocompletions. "
581 help="Experimental: Use Jedi to generate autocompletions. "
582 "Default to True if jedi is installed.").tag(config=True)
582 "Default to True if jedi is installed.").tag(config=True)
583
583
584 jedi_compute_type_timeout = Int(default_value=400,
584 jedi_compute_type_timeout = Int(default_value=400,
585 help="""Experimental: restrict time (in milliseconds) during which Jedi can compute types.
585 help="""Experimental: restrict time (in milliseconds) during which Jedi can compute types.
586 Set to 0 to stop computing types. Non-zero value lower than 100ms may hurt
586 Set to 0 to stop computing types. Non-zero value lower than 100ms may hurt
587 performance by preventing jedi to build its cache.
587 performance by preventing jedi to build its cache.
588 """).tag(config=True)
588 """).tag(config=True)
589
589
590 debug = Bool(default_value=False,
590 debug = Bool(default_value=False,
591 help='Enable debug for the Completer. Mostly print extra '
591 help='Enable debug for the Completer. Mostly print extra '
592 'information for experimental jedi integration.')\
592 'information for experimental jedi integration.')\
593 .tag(config=True)
593 .tag(config=True)
594
594
595 backslash_combining_completions = Bool(True,
595 backslash_combining_completions = Bool(True,
596 help="Enable unicode completions, e.g. \\alpha<tab> . "
596 help="Enable unicode completions, e.g. \\alpha<tab> . "
597 "Includes completion of latex commands, unicode names, and expanding "
597 "Includes completion of latex commands, unicode names, and expanding "
598 "unicode characters back to latex commands.").tag(config=True)
598 "unicode characters back to latex commands.").tag(config=True)
599
599
600
600
601
601
602 def __init__(self, namespace=None, global_namespace=None, **kwargs):
602 def __init__(self, namespace=None, global_namespace=None, **kwargs):
603 """Create a new completer for the command line.
603 """Create a new completer for the command line.
604
604
605 Completer(namespace=ns, global_namespace=ns2) -> completer instance.
605 Completer(namespace=ns, global_namespace=ns2) -> completer instance.
606
606
607 If unspecified, the default namespace where completions are performed
607 If unspecified, the default namespace where completions are performed
608 is __main__ (technically, __main__.__dict__). Namespaces should be
608 is __main__ (technically, __main__.__dict__). Namespaces should be
609 given as dictionaries.
609 given as dictionaries.
610
610
611 An optional second namespace can be given. This allows the completer
611 An optional second namespace can be given. This allows the completer
612 to handle cases where both the local and global scopes need to be
612 to handle cases where both the local and global scopes need to be
613 distinguished.
613 distinguished.
614 """
614 """
615
615
616 # Don't bind to namespace quite yet, but flag whether the user wants a
616 # Don't bind to namespace quite yet, but flag whether the user wants a
617 # specific namespace or to use __main__.__dict__. This will allow us
617 # specific namespace or to use __main__.__dict__. This will allow us
618 # to bind to __main__.__dict__ at completion time, not now.
618 # to bind to __main__.__dict__ at completion time, not now.
619 if namespace is None:
619 if namespace is None:
620 self.use_main_ns = True
620 self.use_main_ns = True
621 else:
621 else:
622 self.use_main_ns = False
622 self.use_main_ns = False
623 self.namespace = namespace
623 self.namespace = namespace
624
624
625 # The global namespace, if given, can be bound directly
625 # The global namespace, if given, can be bound directly
626 if global_namespace is None:
626 if global_namespace is None:
627 self.global_namespace = {}
627 self.global_namespace = {}
628 else:
628 else:
629 self.global_namespace = global_namespace
629 self.global_namespace = global_namespace
630
630
631 self.custom_matchers = []
631 self.custom_matchers = []
632
632
633 super(Completer, self).__init__(**kwargs)
633 super(Completer, self).__init__(**kwargs)
634
634
635 def complete(self, text, state):
635 def complete(self, text, state):
636 """Return the next possible completion for 'text'.
636 """Return the next possible completion for 'text'.
637
637
638 This is called successively with state == 0, 1, 2, ... until it
638 This is called successively with state == 0, 1, 2, ... until it
639 returns None. The completion should begin with 'text'.
639 returns None. The completion should begin with 'text'.
640
640
641 """
641 """
642 if self.use_main_ns:
642 if self.use_main_ns:
643 self.namespace = __main__.__dict__
643 self.namespace = __main__.__dict__
644
644
645 if state == 0:
645 if state == 0:
646 if "." in text:
646 if "." in text:
647 self.matches = self.attr_matches(text)
647 self.matches = self.attr_matches(text)
648 else:
648 else:
649 self.matches = self.global_matches(text)
649 self.matches = self.global_matches(text)
650 try:
650 try:
651 return self.matches[state]
651 return self.matches[state]
652 except IndexError:
652 except IndexError:
653 return None
653 return None
654
654
655 def global_matches(self, text):
655 def global_matches(self, text):
656 """Compute matches when text is a simple name.
656 """Compute matches when text is a simple name.
657
657
658 Return a list of all keywords, built-in functions and names currently
658 Return a list of all keywords, built-in functions and names currently
659 defined in self.namespace or self.global_namespace that match.
659 defined in self.namespace or self.global_namespace that match.
660
660
661 """
661 """
662 matches = []
662 matches = []
663 match_append = matches.append
663 match_append = matches.append
664 n = len(text)
664 n = len(text)
665 for lst in [keyword.kwlist,
665 for lst in [keyword.kwlist,
666 builtin_mod.__dict__.keys(),
666 builtin_mod.__dict__.keys(),
667 self.namespace.keys(),
667 self.namespace.keys(),
668 self.global_namespace.keys()]:
668 self.global_namespace.keys()]:
669 for word in lst:
669 for word in lst:
670 if word[:n] == text and word != "__builtins__":
670 if word[:n] == text and word != "__builtins__":
671 match_append(word)
671 match_append(word)
672
672
673 snake_case_re = re.compile(r"[^_]+(_[^_]+)+?\Z")
673 snake_case_re = re.compile(r"[^_]+(_[^_]+)+?\Z")
674 for lst in [self.namespace.keys(),
674 for lst in [self.namespace.keys(),
675 self.global_namespace.keys()]:
675 self.global_namespace.keys()]:
676 shortened = {"_".join([sub[0] for sub in word.split('_')]) : word
676 shortened = {"_".join([sub[0] for sub in word.split('_')]) : word
677 for word in lst if snake_case_re.match(word)}
677 for word in lst if snake_case_re.match(word)}
678 for word in shortened.keys():
678 for word in shortened.keys():
679 if word[:n] == text and word != "__builtins__":
679 if word[:n] == text and word != "__builtins__":
680 match_append(shortened[word])
680 match_append(shortened[word])
681 return matches
681 return matches
682
682
683 def attr_matches(self, text):
683 def attr_matches(self, text):
684 """Compute matches when text contains a dot.
684 """Compute matches when text contains a dot.
685
685
686 Assuming the text is of the form NAME.NAME....[NAME], and is
686 Assuming the text is of the form NAME.NAME....[NAME], and is
687 evaluatable in self.namespace or self.global_namespace, it will be
687 evaluatable in self.namespace or self.global_namespace, it will be
688 evaluated and its attributes (as revealed by dir()) are used as
688 evaluated and its attributes (as revealed by dir()) are used as
689 possible completions. (For class instances, class members are
689 possible completions. (For class instances, class members are
690 also considered.)
690 also considered.)
691
691
692 WARNING: this can still invoke arbitrary C code, if an object
692 WARNING: this can still invoke arbitrary C code, if an object
693 with a __getattr__ hook is evaluated.
693 with a __getattr__ hook is evaluated.
694
694
695 """
695 """
696
696
697 # Another option, seems to work great. Catches things like ''.<tab>
697 # Another option, seems to work great. Catches things like ''.<tab>
698 m = re.match(r"(\S+(\.\w+)*)\.(\w*)$", text)
698 m = re.match(r"(\S+(\.\w+)*)\.(\w*)$", text)
699
699
700 if m:
700 if m:
701 expr, attr = m.group(1, 3)
701 expr, attr = m.group(1, 3)
702 elif self.greedy:
702 elif self.greedy:
703 m2 = re.match(r"(.+)\.(\w*)$", self.line_buffer)
703 m2 = re.match(r"(.+)\.(\w*)$", self.line_buffer)
704 if not m2:
704 if not m2:
705 return []
705 return []
706 expr, attr = m2.group(1,2)
706 expr, attr = m2.group(1,2)
707 else:
707 else:
708 return []
708 return []
709
709
710 try:
710 try:
711 obj = eval(expr, self.namespace)
711 obj = eval(expr, self.namespace)
712 except:
712 except:
713 try:
713 try:
714 obj = eval(expr, self.global_namespace)
714 obj = eval(expr, self.global_namespace)
715 except:
715 except:
716 return []
716 return []
717
717
718 if self.limit_to__all__ and hasattr(obj, '__all__'):
718 if self.limit_to__all__ and hasattr(obj, '__all__'):
719 words = get__all__entries(obj)
719 words = get__all__entries(obj)
720 else:
720 else:
721 words = dir2(obj)
721 words = dir2(obj)
722
722
723 try:
723 try:
724 words = generics.complete_object(obj, words)
724 words = generics.complete_object(obj, words)
725 except TryNext:
725 except TryNext:
726 pass
726 pass
727 except AssertionError:
727 except AssertionError:
728 raise
728 raise
729 except Exception:
729 except Exception:
730 # Silence errors from completion function
730 # Silence errors from completion function
731 #raise # dbg
731 #raise # dbg
732 pass
732 pass
733 # Build match list to return
733 # Build match list to return
734 n = len(attr)
734 n = len(attr)
735 return [u"%s.%s" % (expr, w) for w in words if w[:n] == attr ]
735 return [u"%s.%s" % (expr, w) for w in words if w[:n] == attr ]
736
736
737
737
738 def get__all__entries(obj):
738 def get__all__entries(obj):
739 """returns the strings in the __all__ attribute"""
739 """returns the strings in the __all__ attribute"""
740 try:
740 try:
741 words = getattr(obj, '__all__')
741 words = getattr(obj, '__all__')
742 except:
742 except:
743 return []
743 return []
744
744
745 return [w for w in words if isinstance(w, str)]
745 return [w for w in words if isinstance(w, str)]
746
746
747
747
748 def match_dict_keys(keys: List[str], prefix: str, delims: str):
748 def match_dict_keys(keys: List[Union[str, bytes]], prefix: str, delims: str) -> Tuple[str, int, List[str]]:
749 """Used by dict_key_matches, matching the prefix to a list of keys
749 """Used by dict_key_matches, matching the prefix to a list of keys
750
750
751 Parameters
751 Parameters
752 ==========
752 ==========
753 keys:
753 keys:
754 list of keys in dictionary currently being completed.
754 list of keys in dictionary currently being completed.
755 prefix:
755 prefix:
756 Part of the text already typed by the user. e.g. `mydict[b'fo`
756 Part of the text already typed by the user. e.g. `mydict[b'fo`
757 delims:
757 delims:
758 String of delimiters to consider when finding the current key.
758 String of delimiters to consider when finding the current key.
759
759
760 Returns
760 Returns
761 =======
761 =======
762
762
763 A tuple of three elements: ``quote``, ``token_start``, ``matched``, with
763 A tuple of three elements: ``quote``, ``token_start``, ``matched``, with
764 ``quote`` being the quote that need to be used to close current string.
764 ``quote`` being the quote that need to be used to close current string.
765 ``token_start`` the position where the replacement should start occurring,
765 ``token_start`` the position where the replacement should start occurring,
766 ``matches`` a list of replacement/completion
766 ``matches`` a list of replacement/completion
767
767
768 """
768 """
769 keys = [k for k in keys if isinstance(k, (str, bytes))]
769 if not prefix:
770 if not prefix:
770 return None, 0, [repr(k) for k in keys
771 return '', 0, [repr(k) for k in keys
771 if isinstance(k, (str, bytes))]
772 if isinstance(k, (str, bytes))]
772 quote_match = re.search('["\']', prefix)
773 quote_match = re.search('["\']', prefix)
774 assert quote_match is not None # silence mypy
773 quote = quote_match.group()
775 quote = quote_match.group()
774 try:
776 try:
775 prefix_str = eval(prefix + quote, {})
777 prefix_str = eval(prefix + quote, {})
776 except Exception:
778 except Exception:
777 return None, 0, []
779 return '', 0, []
778
780
779 pattern = '[^' + ''.join('\\' + c for c in delims) + ']*$'
781 pattern = '[^' + ''.join('\\' + c for c in delims) + ']*$'
780 token_match = re.search(pattern, prefix, re.UNICODE)
782 token_match = re.search(pattern, prefix, re.UNICODE)
783 assert token_match is not None # silence mypy
781 token_start = token_match.start()
784 token_start = token_match.start()
782 token_prefix = token_match.group()
785 token_prefix = token_match.group()
783
786
784 matched = []
787 matched:List[str] = []
785 for key in keys:
788 for key in keys:
786 try:
789 try:
787 if not key.startswith(prefix_str):
790 if not key.startswith(prefix_str):
788 continue
791 continue
789 except (AttributeError, TypeError, UnicodeError):
792 except (AttributeError, TypeError, UnicodeError):
790 # Python 3+ TypeError on b'a'.startswith('a') or vice-versa
793 # Python 3+ TypeError on b'a'.startswith('a') or vice-versa
791 continue
794 continue
792
795
793 # reformat remainder of key to begin with prefix
796 # reformat remainder of key to begin with prefix
794 rem = key[len(prefix_str):]
797 rem = key[len(prefix_str):]
795 # force repr wrapped in '
798 # force repr wrapped in '
796 rem_repr = repr(rem + '"') if isinstance(rem, str) else repr(rem + b'"')
799 rem_repr = repr(rem + '"') if isinstance(rem, str) else repr(rem + b'"')
797 if rem_repr.startswith('u') and prefix[0] not in 'uU':
798 # Found key is unicode, but prefix is Py2 string.
799 # Therefore attempt to interpret key as string.
800 try:
801 rem_repr = repr(rem.encode('ascii') + '"')
802 except UnicodeEncodeError:
803 continue
804
805 rem_repr = rem_repr[1 + rem_repr.index("'"):-2]
800 rem_repr = rem_repr[1 + rem_repr.index("'"):-2]
806 if quote == '"':
801 if quote == '"':
807 # The entered prefix is quoted with ",
802 # The entered prefix is quoted with ",
808 # but the match is quoted with '.
803 # but the match is quoted with '.
809 # A contained " hence needs escaping for comparison:
804 # A contained " hence needs escaping for comparison:
810 rem_repr = rem_repr.replace('"', '\\"')
805 rem_repr = rem_repr.replace('"', '\\"')
811
806
812 # then reinsert prefix from start of token
807 # then reinsert prefix from start of token
813 matched.append('%s%s' % (token_prefix, rem_repr))
808 matched.append('%s%s' % (token_prefix, rem_repr))
814 return quote, token_start, matched
809 return quote, token_start, matched
815
810
816
811
817 def cursor_to_position(text:str, line:int, column:int)->int:
812 def cursor_to_position(text:str, line:int, column:int)->int:
818 """
813 """
819
814
820 Convert the (line,column) position of the cursor in text to an offset in a
815 Convert the (line,column) position of the cursor in text to an offset in a
821 string.
816 string.
822
817
823 Parameters
818 Parameters
824 ----------
819 ----------
825
820
826 text : str
821 text : str
827 The text in which to calculate the cursor offset
822 The text in which to calculate the cursor offset
828 line : int
823 line : int
829 Line of the cursor; 0-indexed
824 Line of the cursor; 0-indexed
830 column : int
825 column : int
831 Column of the cursor 0-indexed
826 Column of the cursor 0-indexed
832
827
833 Return
828 Return
834 ------
829 ------
835 Position of the cursor in ``text``, 0-indexed.
830 Position of the cursor in ``text``, 0-indexed.
836
831
837 See Also
832 See Also
838 --------
833 --------
839 position_to_cursor: reciprocal of this function
834 position_to_cursor: reciprocal of this function
840
835
841 """
836 """
842 lines = text.split('\n')
837 lines = text.split('\n')
843 assert line <= len(lines), '{} <= {}'.format(str(line), str(len(lines)))
838 assert line <= len(lines), '{} <= {}'.format(str(line), str(len(lines)))
844
839
845 return sum(len(l) + 1 for l in lines[:line]) + column
840 return sum(len(l) + 1 for l in lines[:line]) + column
846
841
847 def position_to_cursor(text:str, offset:int)->Tuple[int, int]:
842 def position_to_cursor(text:str, offset:int)->Tuple[int, int]:
848 """
843 """
849 Convert the position of the cursor in text (0 indexed) to a line
844 Convert the position of the cursor in text (0 indexed) to a line
850 number(0-indexed) and a column number (0-indexed) pair
845 number(0-indexed) and a column number (0-indexed) pair
851
846
852 Position should be a valid position in ``text``.
847 Position should be a valid position in ``text``.
853
848
854 Parameters
849 Parameters
855 ----------
850 ----------
856
851
857 text : str
852 text : str
858 The text in which to calculate the cursor offset
853 The text in which to calculate the cursor offset
859 offset : int
854 offset : int
860 Position of the cursor in ``text``, 0-indexed.
855 Position of the cursor in ``text``, 0-indexed.
861
856
862 Return
857 Return
863 ------
858 ------
864 (line, column) : (int, int)
859 (line, column) : (int, int)
865 Line of the cursor; 0-indexed, column of the cursor 0-indexed
860 Line of the cursor; 0-indexed, column of the cursor 0-indexed
866
861
867
862
868 See Also
863 See Also
869 --------
864 --------
870 cursor_to_position : reciprocal of this function
865 cursor_to_position : reciprocal of this function
871
866
872
867
873 """
868 """
874
869
875 assert 0 <= offset <= len(text) , "0 <= %s <= %s" % (offset , len(text))
870 assert 0 <= offset <= len(text) , "0 <= %s <= %s" % (offset , len(text))
876
871
877 before = text[:offset]
872 before = text[:offset]
878 blines = before.split('\n') # ! splitnes trim trailing \n
873 blines = before.split('\n') # ! splitnes trim trailing \n
879 line = before.count('\n')
874 line = before.count('\n')
880 col = len(blines[-1])
875 col = len(blines[-1])
881 return line, col
876 return line, col
882
877
883
878
884 def _safe_isinstance(obj, module, class_name):
879 def _safe_isinstance(obj, module, class_name):
885 """Checks if obj is an instance of module.class_name if loaded
880 """Checks if obj is an instance of module.class_name if loaded
886 """
881 """
887 return (module in sys.modules and
882 return (module in sys.modules and
888 isinstance(obj, getattr(import_module(module), class_name)))
883 isinstance(obj, getattr(import_module(module), class_name)))
889
884
890
885 def back_unicode_name_matches(text:str) -> Tuple[str, Sequence[str]]:
891 def back_unicode_name_matches(text):
886 """Match unicode characters back to unicode name
892 u"""Match unicode characters back to unicode name
893
887
894 This does ``β˜ƒ`` -> ``\\snowman``
888 This does ``β˜ƒ`` -> ``\\snowman``
895
889
896 Note that snowman is not a valid python3 combining character but will be expanded.
890 Note that snowman is not a valid python3 combining character but will be expanded.
897 Though it will not recombine back to the snowman character by the completion machinery.
891 Though it will not recombine back to the snowman character by the completion machinery.
898
892
899 This will not either back-complete standard sequences like \\n, \\b ...
893 This will not either back-complete standard sequences like \\n, \\b ...
900
894
901 Used on Python 3 only.
895 Returns
896 =======
897
898 Return a tuple of
899
902 """
900 """
903 if len(text)<2:
901 if len(text)<2:
904 return u'', ()
902 return '', ()
905 maybe_slash = text[-2]
903 maybe_slash = text[-2]
906 if maybe_slash != '\\':
904 if maybe_slash != '\\':
907 return u'', ()
905 return '', ()
908
906
909 char = text[-1]
907 char = text[-1]
910 # no expand on quote for completion in strings.
908 # no expand on quote for completion in strings.
911 # nor backcomplete standard ascii keys
909 # nor backcomplete standard ascii keys
912 if char in string.ascii_letters or char in ['"',"'"]:
910 if char in string.ascii_letters or char in ['"',"'"]:
913 return u'', ()
911 return '', ()
914 try :
912 try :
915 unic = unicodedata.name(char)
913 unic = unicodedata.name(char)
916 return '\\'+char,['\\'+unic]
914 return '\\'+char,['\\'+unic]
917 except KeyError:
915 except KeyError:
918 pass
916 pass
919 return u'', ()
917 return '', ()
920
918
921 def back_latex_name_matches(text:str):
919 def back_latex_name_matches(text:str):
922 """Match latex characters back to unicode name
920 """Match latex characters back to unicode name
923
921
924 This does ``\\β„΅`` -> ``\\aleph``
922 This does ``\\β„΅`` -> ``\\aleph``
925
923
926 Used on Python 3 only.
924 Used on Python 3 only.
927 """
925 """
928 if len(text)<2:
926 if len(text)<2:
929 return u'', ()
927 return u'', ()
930 maybe_slash = text[-2]
928 maybe_slash = text[-2]
931 if maybe_slash != '\\':
929 if maybe_slash != '\\':
932 return u'', ()
930 return u'', ()
933
931
934
932
935 char = text[-1]
933 char = text[-1]
936 # no expand on quote for completion in strings.
934 # no expand on quote for completion in strings.
937 # nor backcomplete standard ascii keys
935 # nor backcomplete standard ascii keys
938 if char in string.ascii_letters or char in ['"',"'"]:
936 if char in string.ascii_letters or char in ['"',"'"]:
939 return u'', ()
937 return u'', ()
940 try :
938 try :
941 latex = reverse_latex_symbol[char]
939 latex = reverse_latex_symbol[char]
942 # '\\' replace the \ as well
940 # '\\' replace the \ as well
943 return '\\'+char,[latex]
941 return '\\'+char,[latex]
944 except KeyError:
942 except KeyError:
945 pass
943 pass
946 return u'', ()
944 return u'', ()
947
945
948
946
949 def _formatparamchildren(parameter) -> str:
947 def _formatparamchildren(parameter) -> str:
950 """
948 """
951 Get parameter name and value from Jedi Private API
949 Get parameter name and value from Jedi Private API
952
950
953 Jedi does not expose a simple way to get `param=value` from its API.
951 Jedi does not expose a simple way to get `param=value` from its API.
954
952
955 Parameter
953 Parameter
956 =========
954 =========
957
955
958 parameter:
956 parameter:
959 Jedi's function `Param`
957 Jedi's function `Param`
960
958
961 Returns
959 Returns
962 =======
960 =======
963
961
964 A string like 'a', 'b=1', '*args', '**kwargs'
962 A string like 'a', 'b=1', '*args', '**kwargs'
965
963
966
964
967 """
965 """
968 description = parameter.description
966 description = parameter.description
969 if not description.startswith('param '):
967 if not description.startswith('param '):
970 raise ValueError('Jedi function parameter description have change format.'
968 raise ValueError('Jedi function parameter description have change format.'
971 'Expected "param ...", found %r".' % description)
969 'Expected "param ...", found %r".' % description)
972 return description[6:]
970 return description[6:]
973
971
974 def _make_signature(completion)-> str:
972 def _make_signature(completion)-> str:
975 """
973 """
976 Make the signature from a jedi completion
974 Make the signature from a jedi completion
977
975
978 Parameter
976 Parameter
979 =========
977 =========
980
978
981 completion: jedi.Completion
979 completion: jedi.Completion
982 object does not complete a function type
980 object does not complete a function type
983
981
984 Returns
982 Returns
985 =======
983 =======
986
984
987 a string consisting of the function signature, with the parenthesis but
985 a string consisting of the function signature, with the parenthesis but
988 without the function name. example:
986 without the function name. example:
989 `(a, *args, b=1, **kwargs)`
987 `(a, *args, b=1, **kwargs)`
990
988
991 """
989 """
992
990
993 # it looks like this might work on jedi 0.17
991 # it looks like this might work on jedi 0.17
994 if hasattr(completion, 'get_signatures'):
992 if hasattr(completion, 'get_signatures'):
995 signatures = completion.get_signatures()
993 signatures = completion.get_signatures()
996 if not signatures:
994 if not signatures:
997 return '(?)'
995 return '(?)'
998
996
999 c0 = completion.get_signatures()[0]
997 c0 = completion.get_signatures()[0]
1000 return '('+c0.to_string().split('(', maxsplit=1)[1]
998 return '('+c0.to_string().split('(', maxsplit=1)[1]
1001
999
1002 return '(%s)'% ', '.join([f for f in (_formatparamchildren(p) for signature in completion.get_signatures()
1000 return '(%s)'% ', '.join([f for f in (_formatparamchildren(p) for signature in completion.get_signatures()
1003 for p in signature.defined_names()) if f])
1001 for p in signature.defined_names()) if f])
1004
1002
1003
1004 class _CompleteResult(NamedTuple):
1005 matched_text : str
1006 matches: Sequence[str]
1007 matches_origin: Sequence[str]
1008 jedi_matches: Any
1009
1010
1005 class IPCompleter(Completer):
1011 class IPCompleter(Completer):
1006 """Extension of the completer class with IPython-specific features"""
1012 """Extension of the completer class with IPython-specific features"""
1007
1013
1014 __dict_key_regexps: Optional[Dict[bool,Pattern]] = None
1015
1008 @observe('greedy')
1016 @observe('greedy')
1009 def _greedy_changed(self, change):
1017 def _greedy_changed(self, change):
1010 """update the splitter and readline delims when greedy is changed"""
1018 """update the splitter and readline delims when greedy is changed"""
1011 if change['new']:
1019 if change['new']:
1012 self.splitter.delims = GREEDY_DELIMS
1020 self.splitter.delims = GREEDY_DELIMS
1013 else:
1021 else:
1014 self.splitter.delims = DELIMS
1022 self.splitter.delims = DELIMS
1015
1023
1016 dict_keys_only = Bool(False,
1024 dict_keys_only = Bool(False,
1017 help="""Whether to show dict key matches only""")
1025 help="""Whether to show dict key matches only""")
1018
1026
1019 merge_completions = Bool(True,
1027 merge_completions = Bool(True,
1020 help="""Whether to merge completion results into a single list
1028 help="""Whether to merge completion results into a single list
1021
1029
1022 If False, only the completion results from the first non-empty
1030 If False, only the completion results from the first non-empty
1023 completer will be returned.
1031 completer will be returned.
1024 """
1032 """
1025 ).tag(config=True)
1033 ).tag(config=True)
1026 omit__names = Enum((0,1,2), default_value=2,
1034 omit__names = Enum((0,1,2), default_value=2,
1027 help="""Instruct the completer to omit private method names
1035 help="""Instruct the completer to omit private method names
1028
1036
1029 Specifically, when completing on ``object.<tab>``.
1037 Specifically, when completing on ``object.<tab>``.
1030
1038
1031 When 2 [default]: all names that start with '_' will be excluded.
1039 When 2 [default]: all names that start with '_' will be excluded.
1032
1040
1033 When 1: all 'magic' names (``__foo__``) will be excluded.
1041 When 1: all 'magic' names (``__foo__``) will be excluded.
1034
1042
1035 When 0: nothing will be excluded.
1043 When 0: nothing will be excluded.
1036 """
1044 """
1037 ).tag(config=True)
1045 ).tag(config=True)
1038 limit_to__all__ = Bool(False,
1046 limit_to__all__ = Bool(False,
1039 help="""
1047 help="""
1040 DEPRECATED as of version 5.0.
1048 DEPRECATED as of version 5.0.
1041
1049
1042 Instruct the completer to use __all__ for the completion
1050 Instruct the completer to use __all__ for the completion
1043
1051
1044 Specifically, when completing on ``object.<tab>``.
1052 Specifically, when completing on ``object.<tab>``.
1045
1053
1046 When True: only those names in obj.__all__ will be included.
1054 When True: only those names in obj.__all__ will be included.
1047
1055
1048 When False [default]: the __all__ attribute is ignored
1056 When False [default]: the __all__ attribute is ignored
1049 """,
1057 """,
1050 ).tag(config=True)
1058 ).tag(config=True)
1051
1059
1052 profile_completions = Bool(
1060 profile_completions = Bool(
1053 default_value=False,
1061 default_value=False,
1054 help="If True, emit profiling data for completion subsystem using cProfile."
1062 help="If True, emit profiling data for completion subsystem using cProfile."
1055 ).tag(config=True)
1063 ).tag(config=True)
1056
1064
1057 profiler_output_dir = Unicode(
1065 profiler_output_dir = Unicode(
1058 default_value=".completion_profiles",
1066 default_value=".completion_profiles",
1059 help="Template for path at which to output profile data for completions."
1067 help="Template for path at which to output profile data for completions."
1060 ).tag(config=True)
1068 ).tag(config=True)
1061
1069
1062 @observe('limit_to__all__')
1070 @observe('limit_to__all__')
1063 def _limit_to_all_changed(self, change):
1071 def _limit_to_all_changed(self, change):
1064 warnings.warn('`IPython.core.IPCompleter.limit_to__all__` configuration '
1072 warnings.warn('`IPython.core.IPCompleter.limit_to__all__` configuration '
1065 'value has been deprecated since IPython 5.0, will be made to have '
1073 'value has been deprecated since IPython 5.0, will be made to have '
1066 'no effects and then removed in future version of IPython.',
1074 'no effects and then removed in future version of IPython.',
1067 UserWarning)
1075 UserWarning)
1068
1076
1069 def __init__(self, shell=None, namespace=None, global_namespace=None,
1077 def __init__(self, shell=None, namespace=None, global_namespace=None,
1070 use_readline=_deprecation_readline_sentinel, config=None, **kwargs):
1078 use_readline=_deprecation_readline_sentinel, config=None, **kwargs):
1071 """IPCompleter() -> completer
1079 """IPCompleter() -> completer
1072
1080
1073 Return a completer object.
1081 Return a completer object.
1074
1082
1075 Parameters
1083 Parameters
1076 ----------
1084 ----------
1077
1085
1078 shell
1086 shell
1079 a pointer to the ipython shell itself. This is needed
1087 a pointer to the ipython shell itself. This is needed
1080 because this completer knows about magic functions, and those can
1088 because this completer knows about magic functions, and those can
1081 only be accessed via the ipython instance.
1089 only be accessed via the ipython instance.
1082
1090
1083 namespace : dict, optional
1091 namespace : dict, optional
1084 an optional dict where completions are performed.
1092 an optional dict where completions are performed.
1085
1093
1086 global_namespace : dict, optional
1094 global_namespace : dict, optional
1087 secondary optional dict for completions, to
1095 secondary optional dict for completions, to
1088 handle cases (such as IPython embedded inside functions) where
1096 handle cases (such as IPython embedded inside functions) where
1089 both Python scopes are visible.
1097 both Python scopes are visible.
1090
1098
1091 use_readline : bool, optional
1099 use_readline : bool, optional
1092 DEPRECATED, ignored since IPython 6.0, will have no effects
1100 DEPRECATED, ignored since IPython 6.0, will have no effects
1093 """
1101 """
1094
1102
1095 self.magic_escape = ESC_MAGIC
1103 self.magic_escape = ESC_MAGIC
1096 self.splitter = CompletionSplitter()
1104 self.splitter = CompletionSplitter()
1097
1105
1098 if use_readline is not _deprecation_readline_sentinel:
1106 if use_readline is not _deprecation_readline_sentinel:
1099 warnings.warn('The `use_readline` parameter is deprecated and ignored since IPython 6.0.',
1107 warnings.warn('The `use_readline` parameter is deprecated and ignored since IPython 6.0.',
1100 DeprecationWarning, stacklevel=2)
1108 DeprecationWarning, stacklevel=2)
1101
1109
1102 # _greedy_changed() depends on splitter and readline being defined:
1110 # _greedy_changed() depends on splitter and readline being defined:
1103 Completer.__init__(self, namespace=namespace, global_namespace=global_namespace,
1111 Completer.__init__(self, namespace=namespace, global_namespace=global_namespace,
1104 config=config, **kwargs)
1112 config=config, **kwargs)
1105
1113
1106 # List where completion matches will be stored
1114 # List where completion matches will be stored
1107 self.matches = []
1115 self.matches = []
1108 self.shell = shell
1116 self.shell = shell
1109 # Regexp to split filenames with spaces in them
1117 # Regexp to split filenames with spaces in them
1110 self.space_name_re = re.compile(r'([^\\] )')
1118 self.space_name_re = re.compile(r'([^\\] )')
1111 # Hold a local ref. to glob.glob for speed
1119 # Hold a local ref. to glob.glob for speed
1112 self.glob = glob.glob
1120 self.glob = glob.glob
1113
1121
1114 # Determine if we are running on 'dumb' terminals, like (X)Emacs
1122 # Determine if we are running on 'dumb' terminals, like (X)Emacs
1115 # buffers, to avoid completion problems.
1123 # buffers, to avoid completion problems.
1116 term = os.environ.get('TERM','xterm')
1124 term = os.environ.get('TERM','xterm')
1117 self.dumb_terminal = term in ['dumb','emacs']
1125 self.dumb_terminal = term in ['dumb','emacs']
1118
1126
1119 # Special handling of backslashes needed in win32 platforms
1127 # Special handling of backslashes needed in win32 platforms
1120 if sys.platform == "win32":
1128 if sys.platform == "win32":
1121 self.clean_glob = self._clean_glob_win32
1129 self.clean_glob = self._clean_glob_win32
1122 else:
1130 else:
1123 self.clean_glob = self._clean_glob
1131 self.clean_glob = self._clean_glob
1124
1132
1125 #regexp to parse docstring for function signature
1133 #regexp to parse docstring for function signature
1126 self.docstring_sig_re = re.compile(r'^[\w|\s.]+\(([^)]*)\).*')
1134 self.docstring_sig_re = re.compile(r'^[\w|\s.]+\(([^)]*)\).*')
1127 self.docstring_kwd_re = re.compile(r'[\s|\[]*(\w+)(?:\s*=\s*.*)')
1135 self.docstring_kwd_re = re.compile(r'[\s|\[]*(\w+)(?:\s*=\s*.*)')
1128 #use this if positional argument name is also needed
1136 #use this if positional argument name is also needed
1129 #= re.compile(r'[\s|\[]*(\w+)(?:\s*=?\s*.*)')
1137 #= re.compile(r'[\s|\[]*(\w+)(?:\s*=?\s*.*)')
1130
1138
1131 self.magic_arg_matchers = [
1139 self.magic_arg_matchers = [
1132 self.magic_config_matches,
1140 self.magic_config_matches,
1133 self.magic_color_matches,
1141 self.magic_color_matches,
1134 ]
1142 ]
1135
1143
1136 # This is set externally by InteractiveShell
1144 # This is set externally by InteractiveShell
1137 self.custom_completers = None
1145 self.custom_completers = None
1138
1146
1139 # This is a list of names of unicode characters that can be completed
1147 # This is a list of names of unicode characters that can be completed
1140 # into their corresponding unicode value. The list is large, so we
1148 # into their corresponding unicode value. The list is large, so we
1141 # laziliy initialize it on first use. Consuming code should access this
1149 # laziliy initialize it on first use. Consuming code should access this
1142 # attribute through the `@unicode_names` property.
1150 # attribute through the `@unicode_names` property.
1143 self._unicode_names = None
1151 self._unicode_names = None
1144
1152
1145 @property
1153 @property
1146 def matchers(self):
1154 def matchers(self) -> List[Any]:
1147 """All active matcher routines for completion"""
1155 """All active matcher routines for completion"""
1148 if self.dict_keys_only:
1156 if self.dict_keys_only:
1149 return [self.dict_key_matches]
1157 return [self.dict_key_matches]
1150
1158
1151 if self.use_jedi:
1159 if self.use_jedi:
1152 return [
1160 return [
1153 *self.custom_matchers,
1161 *self.custom_matchers,
1154 self.file_matches,
1162 self.file_matches,
1155 self.magic_matches,
1163 self.magic_matches,
1156 self.dict_key_matches,
1164 self.dict_key_matches,
1157 ]
1165 ]
1158 else:
1166 else:
1159 return [
1167 return [
1160 *self.custom_matchers,
1168 *self.custom_matchers,
1161 self.python_matches,
1169 self.python_matches,
1162 self.file_matches,
1170 self.file_matches,
1163 self.magic_matches,
1171 self.magic_matches,
1164 self.python_func_kw_matches,
1172 self.python_func_kw_matches,
1165 self.dict_key_matches,
1173 self.dict_key_matches,
1166 ]
1174 ]
1167
1175
1168 def all_completions(self, text) -> List[str]:
1176 def all_completions(self, text:str) -> List[str]:
1169 """
1177 """
1170 Wrapper around the completion methods for the benefit of emacs.
1178 Wrapper around the completion methods for the benefit of emacs.
1171 """
1179 """
1172 prefix = text.rpartition('.')[0]
1180 prefix = text.rpartition('.')[0]
1173 with provisionalcompleter():
1181 with provisionalcompleter():
1174 return ['.'.join([prefix, c.text]) if prefix and self.use_jedi else c.text
1182 return ['.'.join([prefix, c.text]) if prefix and self.use_jedi else c.text
1175 for c in self.completions(text, len(text))]
1183 for c in self.completions(text, len(text))]
1176
1184
1177 return self.complete(text)[1]
1185 return self.complete(text)[1]
1178
1186
1179 def _clean_glob(self, text):
1187 def _clean_glob(self, text:str):
1180 return self.glob("%s*" % text)
1188 return self.glob("%s*" % text)
1181
1189
1182 def _clean_glob_win32(self,text):
1190 def _clean_glob_win32(self,text:str):
1183 return [f.replace("\\","/")
1191 return [f.replace("\\","/")
1184 for f in self.glob("%s*" % text)]
1192 for f in self.glob("%s*" % text)]
1185
1193
1186 def file_matches(self, text):
1194 def file_matches(self, text:str)->List[str]:
1187 """Match filenames, expanding ~USER type strings.
1195 """Match filenames, expanding ~USER type strings.
1188
1196
1189 Most of the seemingly convoluted logic in this completer is an
1197 Most of the seemingly convoluted logic in this completer is an
1190 attempt to handle filenames with spaces in them. And yet it's not
1198 attempt to handle filenames with spaces in them. And yet it's not
1191 quite perfect, because Python's readline doesn't expose all of the
1199 quite perfect, because Python's readline doesn't expose all of the
1192 GNU readline details needed for this to be done correctly.
1200 GNU readline details needed for this to be done correctly.
1193
1201
1194 For a filename with a space in it, the printed completions will be
1202 For a filename with a space in it, the printed completions will be
1195 only the parts after what's already been typed (instead of the
1203 only the parts after what's already been typed (instead of the
1196 full completions, as is normally done). I don't think with the
1204 full completions, as is normally done). I don't think with the
1197 current (as of Python 2.3) Python readline it's possible to do
1205 current (as of Python 2.3) Python readline it's possible to do
1198 better."""
1206 better."""
1199
1207
1200 # chars that require escaping with backslash - i.e. chars
1208 # chars that require escaping with backslash - i.e. chars
1201 # that readline treats incorrectly as delimiters, but we
1209 # that readline treats incorrectly as delimiters, but we
1202 # don't want to treat as delimiters in filename matching
1210 # don't want to treat as delimiters in filename matching
1203 # when escaped with backslash
1211 # when escaped with backslash
1204 if text.startswith('!'):
1212 if text.startswith('!'):
1205 text = text[1:]
1213 text = text[1:]
1206 text_prefix = u'!'
1214 text_prefix = u'!'
1207 else:
1215 else:
1208 text_prefix = u''
1216 text_prefix = u''
1209
1217
1210 text_until_cursor = self.text_until_cursor
1218 text_until_cursor = self.text_until_cursor
1211 # track strings with open quotes
1219 # track strings with open quotes
1212 open_quotes = has_open_quotes(text_until_cursor)
1220 open_quotes = has_open_quotes(text_until_cursor)
1213
1221
1214 if '(' in text_until_cursor or '[' in text_until_cursor:
1222 if '(' in text_until_cursor or '[' in text_until_cursor:
1215 lsplit = text
1223 lsplit = text
1216 else:
1224 else:
1217 try:
1225 try:
1218 # arg_split ~ shlex.split, but with unicode bugs fixed by us
1226 # arg_split ~ shlex.split, but with unicode bugs fixed by us
1219 lsplit = arg_split(text_until_cursor)[-1]
1227 lsplit = arg_split(text_until_cursor)[-1]
1220 except ValueError:
1228 except ValueError:
1221 # typically an unmatched ", or backslash without escaped char.
1229 # typically an unmatched ", or backslash without escaped char.
1222 if open_quotes:
1230 if open_quotes:
1223 lsplit = text_until_cursor.split(open_quotes)[-1]
1231 lsplit = text_until_cursor.split(open_quotes)[-1]
1224 else:
1232 else:
1225 return []
1233 return []
1226 except IndexError:
1234 except IndexError:
1227 # tab pressed on empty line
1235 # tab pressed on empty line
1228 lsplit = ""
1236 lsplit = ""
1229
1237
1230 if not open_quotes and lsplit != protect_filename(lsplit):
1238 if not open_quotes and lsplit != protect_filename(lsplit):
1231 # if protectables are found, do matching on the whole escaped name
1239 # if protectables are found, do matching on the whole escaped name
1232 has_protectables = True
1240 has_protectables = True
1233 text0,text = text,lsplit
1241 text0,text = text,lsplit
1234 else:
1242 else:
1235 has_protectables = False
1243 has_protectables = False
1236 text = os.path.expanduser(text)
1244 text = os.path.expanduser(text)
1237
1245
1238 if text == "":
1246 if text == "":
1239 return [text_prefix + protect_filename(f) for f in self.glob("*")]
1247 return [text_prefix + protect_filename(f) for f in self.glob("*")]
1240
1248
1241 # Compute the matches from the filesystem
1249 # Compute the matches from the filesystem
1242 if sys.platform == 'win32':
1250 if sys.platform == 'win32':
1243 m0 = self.clean_glob(text)
1251 m0 = self.clean_glob(text)
1244 else:
1252 else:
1245 m0 = self.clean_glob(text.replace('\\', ''))
1253 m0 = self.clean_glob(text.replace('\\', ''))
1246
1254
1247 if has_protectables:
1255 if has_protectables:
1248 # If we had protectables, we need to revert our changes to the
1256 # If we had protectables, we need to revert our changes to the
1249 # beginning of filename so that we don't double-write the part
1257 # beginning of filename so that we don't double-write the part
1250 # of the filename we have so far
1258 # of the filename we have so far
1251 len_lsplit = len(lsplit)
1259 len_lsplit = len(lsplit)
1252 matches = [text_prefix + text0 +
1260 matches = [text_prefix + text0 +
1253 protect_filename(f[len_lsplit:]) for f in m0]
1261 protect_filename(f[len_lsplit:]) for f in m0]
1254 else:
1262 else:
1255 if open_quotes:
1263 if open_quotes:
1256 # if we have a string with an open quote, we don't need to
1264 # if we have a string with an open quote, we don't need to
1257 # protect the names beyond the quote (and we _shouldn't_, as
1265 # protect the names beyond the quote (and we _shouldn't_, as
1258 # it would cause bugs when the filesystem call is made).
1266 # it would cause bugs when the filesystem call is made).
1259 matches = m0 if sys.platform == "win32" else\
1267 matches = m0 if sys.platform == "win32" else\
1260 [protect_filename(f, open_quotes) for f in m0]
1268 [protect_filename(f, open_quotes) for f in m0]
1261 else:
1269 else:
1262 matches = [text_prefix +
1270 matches = [text_prefix +
1263 protect_filename(f) for f in m0]
1271 protect_filename(f) for f in m0]
1264
1272
1265 # Mark directories in input list by appending '/' to their names.
1273 # Mark directories in input list by appending '/' to their names.
1266 return [x+'/' if os.path.isdir(x) else x for x in matches]
1274 return [x+'/' if os.path.isdir(x) else x for x in matches]
1267
1275
1268 def magic_matches(self, text):
1276 def magic_matches(self, text:str):
1269 """Match magics"""
1277 """Match magics"""
1270 # Get all shell magics now rather than statically, so magics loaded at
1278 # Get all shell magics now rather than statically, so magics loaded at
1271 # runtime show up too.
1279 # runtime show up too.
1272 lsm = self.shell.magics_manager.lsmagic()
1280 lsm = self.shell.magics_manager.lsmagic()
1273 line_magics = lsm['line']
1281 line_magics = lsm['line']
1274 cell_magics = lsm['cell']
1282 cell_magics = lsm['cell']
1275 pre = self.magic_escape
1283 pre = self.magic_escape
1276 pre2 = pre+pre
1284 pre2 = pre+pre
1277
1285
1278 explicit_magic = text.startswith(pre)
1286 explicit_magic = text.startswith(pre)
1279
1287
1280 # Completion logic:
1288 # Completion logic:
1281 # - user gives %%: only do cell magics
1289 # - user gives %%: only do cell magics
1282 # - user gives %: do both line and cell magics
1290 # - user gives %: do both line and cell magics
1283 # - no prefix: do both
1291 # - no prefix: do both
1284 # In other words, line magics are skipped if the user gives %% explicitly
1292 # In other words, line magics are skipped if the user gives %% explicitly
1285 #
1293 #
1286 # We also exclude magics that match any currently visible names:
1294 # We also exclude magics that match any currently visible names:
1287 # https://github.com/ipython/ipython/issues/4877, unless the user has
1295 # https://github.com/ipython/ipython/issues/4877, unless the user has
1288 # typed a %:
1296 # typed a %:
1289 # https://github.com/ipython/ipython/issues/10754
1297 # https://github.com/ipython/ipython/issues/10754
1290 bare_text = text.lstrip(pre)
1298 bare_text = text.lstrip(pre)
1291 global_matches = self.global_matches(bare_text)
1299 global_matches = self.global_matches(bare_text)
1292 if not explicit_magic:
1300 if not explicit_magic:
1293 def matches(magic):
1301 def matches(magic):
1294 """
1302 """
1295 Filter magics, in particular remove magics that match
1303 Filter magics, in particular remove magics that match
1296 a name present in global namespace.
1304 a name present in global namespace.
1297 """
1305 """
1298 return ( magic.startswith(bare_text) and
1306 return ( magic.startswith(bare_text) and
1299 magic not in global_matches )
1307 magic not in global_matches )
1300 else:
1308 else:
1301 def matches(magic):
1309 def matches(magic):
1302 return magic.startswith(bare_text)
1310 return magic.startswith(bare_text)
1303
1311
1304 comp = [ pre2+m for m in cell_magics if matches(m)]
1312 comp = [ pre2+m for m in cell_magics if matches(m)]
1305 if not text.startswith(pre2):
1313 if not text.startswith(pre2):
1306 comp += [ pre+m for m in line_magics if matches(m)]
1314 comp += [ pre+m for m in line_magics if matches(m)]
1307
1315
1308 return comp
1316 return comp
1309
1317
1310 def magic_config_matches(self, text:str) -> List[str]:
1318 def magic_config_matches(self, text:str) -> List[str]:
1311 """ Match class names and attributes for %config magic """
1319 """ Match class names and attributes for %config magic """
1312 texts = text.strip().split()
1320 texts = text.strip().split()
1313
1321
1314 if len(texts) > 0 and (texts[0] == 'config' or texts[0] == '%config'):
1322 if len(texts) > 0 and (texts[0] == 'config' or texts[0] == '%config'):
1315 # get all configuration classes
1323 # get all configuration classes
1316 classes = sorted(set([ c for c in self.shell.configurables
1324 classes = sorted(set([ c for c in self.shell.configurables
1317 if c.__class__.class_traits(config=True)
1325 if c.__class__.class_traits(config=True)
1318 ]), key=lambda x: x.__class__.__name__)
1326 ]), key=lambda x: x.__class__.__name__)
1319 classnames = [ c.__class__.__name__ for c in classes ]
1327 classnames = [ c.__class__.__name__ for c in classes ]
1320
1328
1321 # return all classnames if config or %config is given
1329 # return all classnames if config or %config is given
1322 if len(texts) == 1:
1330 if len(texts) == 1:
1323 return classnames
1331 return classnames
1324
1332
1325 # match classname
1333 # match classname
1326 classname_texts = texts[1].split('.')
1334 classname_texts = texts[1].split('.')
1327 classname = classname_texts[0]
1335 classname = classname_texts[0]
1328 classname_matches = [ c for c in classnames
1336 classname_matches = [ c for c in classnames
1329 if c.startswith(classname) ]
1337 if c.startswith(classname) ]
1330
1338
1331 # return matched classes or the matched class with attributes
1339 # return matched classes or the matched class with attributes
1332 if texts[1].find('.') < 0:
1340 if texts[1].find('.') < 0:
1333 return classname_matches
1341 return classname_matches
1334 elif len(classname_matches) == 1 and \
1342 elif len(classname_matches) == 1 and \
1335 classname_matches[0] == classname:
1343 classname_matches[0] == classname:
1336 cls = classes[classnames.index(classname)].__class__
1344 cls = classes[classnames.index(classname)].__class__
1337 help = cls.class_get_help()
1345 help = cls.class_get_help()
1338 # strip leading '--' from cl-args:
1346 # strip leading '--' from cl-args:
1339 help = re.sub(re.compile(r'^--', re.MULTILINE), '', help)
1347 help = re.sub(re.compile(r'^--', re.MULTILINE), '', help)
1340 return [ attr.split('=')[0]
1348 return [ attr.split('=')[0]
1341 for attr in help.strip().splitlines()
1349 for attr in help.strip().splitlines()
1342 if attr.startswith(texts[1]) ]
1350 if attr.startswith(texts[1]) ]
1343 return []
1351 return []
1344
1352
1345 def magic_color_matches(self, text:str) -> List[str] :
1353 def magic_color_matches(self, text:str) -> List[str] :
1346 """ Match color schemes for %colors magic"""
1354 """ Match color schemes for %colors magic"""
1347 texts = text.split()
1355 texts = text.split()
1348 if text.endswith(' '):
1356 if text.endswith(' '):
1349 # .split() strips off the trailing whitespace. Add '' back
1357 # .split() strips off the trailing whitespace. Add '' back
1350 # so that: '%colors ' -> ['%colors', '']
1358 # so that: '%colors ' -> ['%colors', '']
1351 texts.append('')
1359 texts.append('')
1352
1360
1353 if len(texts) == 2 and (texts[0] == 'colors' or texts[0] == '%colors'):
1361 if len(texts) == 2 and (texts[0] == 'colors' or texts[0] == '%colors'):
1354 prefix = texts[1]
1362 prefix = texts[1]
1355 return [ color for color in InspectColors.keys()
1363 return [ color for color in InspectColors.keys()
1356 if color.startswith(prefix) ]
1364 if color.startswith(prefix) ]
1357 return []
1365 return []
1358
1366
1359 def _jedi_matches(self, cursor_column:int, cursor_line:int, text:str):
1367 def _jedi_matches(self, cursor_column:int, cursor_line:int, text:str) -> Iterable[Any]:
1360 """
1368 """
1361
1369
1362 Return a list of :any:`jedi.api.Completions` object from a ``text`` and
1370 Return a list of :any:`jedi.api.Completions` object from a ``text`` and
1363 cursor position.
1371 cursor position.
1364
1372
1365 Parameters
1373 Parameters
1366 ----------
1374 ----------
1367 cursor_column : int
1375 cursor_column : int
1368 column position of the cursor in ``text``, 0-indexed.
1376 column position of the cursor in ``text``, 0-indexed.
1369 cursor_line : int
1377 cursor_line : int
1370 line position of the cursor in ``text``, 0-indexed
1378 line position of the cursor in ``text``, 0-indexed
1371 text : str
1379 text : str
1372 text to complete
1380 text to complete
1373
1381
1374 Debugging
1382 Debugging
1375 ---------
1383 ---------
1376
1384
1377 If ``IPCompleter.debug`` is ``True`` may return a :any:`_FakeJediCompletion`
1385 If ``IPCompleter.debug`` is ``True`` may return a :any:`_FakeJediCompletion`
1378 object containing a string with the Jedi debug information attached.
1386 object containing a string with the Jedi debug information attached.
1379 """
1387 """
1380 namespaces = [self.namespace]
1388 namespaces = [self.namespace]
1381 if self.global_namespace is not None:
1389 if self.global_namespace is not None:
1382 namespaces.append(self.global_namespace)
1390 namespaces.append(self.global_namespace)
1383
1391
1384 completion_filter = lambda x:x
1392 completion_filter = lambda x:x
1385 offset = cursor_to_position(text, cursor_line, cursor_column)
1393 offset = cursor_to_position(text, cursor_line, cursor_column)
1386 # filter output if we are completing for object members
1394 # filter output if we are completing for object members
1387 if offset:
1395 if offset:
1388 pre = text[offset-1]
1396 pre = text[offset-1]
1389 if pre == '.':
1397 if pre == '.':
1390 if self.omit__names == 2:
1398 if self.omit__names == 2:
1391 completion_filter = lambda c:not c.name.startswith('_')
1399 completion_filter = lambda c:not c.name.startswith('_')
1392 elif self.omit__names == 1:
1400 elif self.omit__names == 1:
1393 completion_filter = lambda c:not (c.name.startswith('__') and c.name.endswith('__'))
1401 completion_filter = lambda c:not (c.name.startswith('__') and c.name.endswith('__'))
1394 elif self.omit__names == 0:
1402 elif self.omit__names == 0:
1395 completion_filter = lambda x:x
1403 completion_filter = lambda x:x
1396 else:
1404 else:
1397 raise ValueError("Don't understand self.omit__names == {}".format(self.omit__names))
1405 raise ValueError("Don't understand self.omit__names == {}".format(self.omit__names))
1398
1406
1399 interpreter = jedi.Interpreter(text[:offset], namespaces)
1407 interpreter = jedi.Interpreter(text[:offset], namespaces)
1400 try_jedi = True
1408 try_jedi = True
1401
1409
1402 try:
1410 try:
1403 # find the first token in the current tree -- if it is a ' or " then we are in a string
1411 # find the first token in the current tree -- if it is a ' or " then we are in a string
1404 completing_string = False
1412 completing_string = False
1405 try:
1413 try:
1406 first_child = next(c for c in interpreter._get_module().tree_node.children if hasattr(c, 'value'))
1414 first_child = next(c for c in interpreter._get_module().tree_node.children if hasattr(c, 'value'))
1407 except StopIteration:
1415 except StopIteration:
1408 pass
1416 pass
1409 else:
1417 else:
1410 # note the value may be ', ", or it may also be ''' or """, or
1418 # note the value may be ', ", or it may also be ''' or """, or
1411 # in some cases, """what/you/typed..., but all of these are
1419 # in some cases, """what/you/typed..., but all of these are
1412 # strings.
1420 # strings.
1413 completing_string = len(first_child.value) > 0 and first_child.value[0] in {"'", '"'}
1421 completing_string = len(first_child.value) > 0 and first_child.value[0] in {"'", '"'}
1414
1422
1415 # if we are in a string jedi is likely not the right candidate for
1423 # if we are in a string jedi is likely not the right candidate for
1416 # now. Skip it.
1424 # now. Skip it.
1417 try_jedi = not completing_string
1425 try_jedi = not completing_string
1418 except Exception as e:
1426 except Exception as e:
1419 # many of things can go wrong, we are using private API just don't crash.
1427 # many of things can go wrong, we are using private API just don't crash.
1420 if self.debug:
1428 if self.debug:
1421 print("Error detecting if completing a non-finished string :", e, '|')
1429 print("Error detecting if completing a non-finished string :", e, '|')
1422
1430
1423 if not try_jedi:
1431 if not try_jedi:
1424 return []
1432 return []
1425 try:
1433 try:
1426 return filter(completion_filter, interpreter.complete(column=cursor_column, line=cursor_line + 1))
1434 return filter(completion_filter, interpreter.complete(column=cursor_column, line=cursor_line + 1))
1427 except Exception as e:
1435 except Exception as e:
1428 if self.debug:
1436 if self.debug:
1429 return [_FakeJediCompletion('Oops Jedi has crashed, please report a bug with the following:\n"""\n%s\ns"""' % (e))]
1437 return [_FakeJediCompletion('Oops Jedi has crashed, please report a bug with the following:\n"""\n%s\ns"""' % (e))]
1430 else:
1438 else:
1431 return []
1439 return []
1432
1440
1433 def python_matches(self, text):
1441 def python_matches(self, text:str)->list[str]:
1434 """Match attributes or global python names"""
1442 """Match attributes or global python names"""
1435 if "." in text:
1443 if "." in text:
1436 try:
1444 try:
1437 matches = self.attr_matches(text)
1445 matches = self.attr_matches(text)
1438 if text.endswith('.') and self.omit__names:
1446 if text.endswith('.') and self.omit__names:
1439 if self.omit__names == 1:
1447 if self.omit__names == 1:
1440 # true if txt is _not_ a __ name, false otherwise:
1448 # true if txt is _not_ a __ name, false otherwise:
1441 no__name = (lambda txt:
1449 no__name = (lambda txt:
1442 re.match(r'.*\.__.*?__',txt) is None)
1450 re.match(r'.*\.__.*?__',txt) is None)
1443 else:
1451 else:
1444 # true if txt is _not_ a _ name, false otherwise:
1452 # true if txt is _not_ a _ name, false otherwise:
1445 no__name = (lambda txt:
1453 no__name = (lambda txt:
1446 re.match(r'\._.*?',txt[txt.rindex('.'):]) is None)
1454 re.match(r'\._.*?',txt[txt.rindex('.'):]) is None)
1447 matches = filter(no__name, matches)
1455 matches = filter(no__name, matches)
1448 except NameError:
1456 except NameError:
1449 # catches <undefined attributes>.<tab>
1457 # catches <undefined attributes>.<tab>
1450 matches = []
1458 matches = []
1451 else:
1459 else:
1452 matches = self.global_matches(text)
1460 matches = self.global_matches(text)
1453 return matches
1461 return matches
1454
1462
1455 def _default_arguments_from_docstring(self, doc):
1463 def _default_arguments_from_docstring(self, doc):
1456 """Parse the first line of docstring for call signature.
1464 """Parse the first line of docstring for call signature.
1457
1465
1458 Docstring should be of the form 'min(iterable[, key=func])\n'.
1466 Docstring should be of the form 'min(iterable[, key=func])\n'.
1459 It can also parse cython docstring of the form
1467 It can also parse cython docstring of the form
1460 'Minuit.migrad(self, int ncall=10000, resume=True, int nsplit=1)'.
1468 'Minuit.migrad(self, int ncall=10000, resume=True, int nsplit=1)'.
1461 """
1469 """
1462 if doc is None:
1470 if doc is None:
1463 return []
1471 return []
1464
1472
1465 #care only the firstline
1473 #care only the firstline
1466 line = doc.lstrip().splitlines()[0]
1474 line = doc.lstrip().splitlines()[0]
1467
1475
1468 #p = re.compile(r'^[\w|\s.]+\(([^)]*)\).*')
1476 #p = re.compile(r'^[\w|\s.]+\(([^)]*)\).*')
1469 #'min(iterable[, key=func])\n' -> 'iterable[, key=func]'
1477 #'min(iterable[, key=func])\n' -> 'iterable[, key=func]'
1470 sig = self.docstring_sig_re.search(line)
1478 sig = self.docstring_sig_re.search(line)
1471 if sig is None:
1479 if sig is None:
1472 return []
1480 return []
1473 # iterable[, key=func]' -> ['iterable[' ,' key=func]']
1481 # iterable[, key=func]' -> ['iterable[' ,' key=func]']
1474 sig = sig.groups()[0].split(',')
1482 sig = sig.groups()[0].split(',')
1475 ret = []
1483 ret = []
1476 for s in sig:
1484 for s in sig:
1477 #re.compile(r'[\s|\[]*(\w+)(?:\s*=\s*.*)')
1485 #re.compile(r'[\s|\[]*(\w+)(?:\s*=\s*.*)')
1478 ret += self.docstring_kwd_re.findall(s)
1486 ret += self.docstring_kwd_re.findall(s)
1479 return ret
1487 return ret
1480
1488
1481 def _default_arguments(self, obj):
1489 def _default_arguments(self, obj):
1482 """Return the list of default arguments of obj if it is callable,
1490 """Return the list of default arguments of obj if it is callable,
1483 or empty list otherwise."""
1491 or empty list otherwise."""
1484 call_obj = obj
1492 call_obj = obj
1485 ret = []
1493 ret = []
1486 if inspect.isbuiltin(obj):
1494 if inspect.isbuiltin(obj):
1487 pass
1495 pass
1488 elif not (inspect.isfunction(obj) or inspect.ismethod(obj)):
1496 elif not (inspect.isfunction(obj) or inspect.ismethod(obj)):
1489 if inspect.isclass(obj):
1497 if inspect.isclass(obj):
1490 #for cython embedsignature=True the constructor docstring
1498 #for cython embedsignature=True the constructor docstring
1491 #belongs to the object itself not __init__
1499 #belongs to the object itself not __init__
1492 ret += self._default_arguments_from_docstring(
1500 ret += self._default_arguments_from_docstring(
1493 getattr(obj, '__doc__', ''))
1501 getattr(obj, '__doc__', ''))
1494 # for classes, check for __init__,__new__
1502 # for classes, check for __init__,__new__
1495 call_obj = (getattr(obj, '__init__', None) or
1503 call_obj = (getattr(obj, '__init__', None) or
1496 getattr(obj, '__new__', None))
1504 getattr(obj, '__new__', None))
1497 # for all others, check if they are __call__able
1505 # for all others, check if they are __call__able
1498 elif hasattr(obj, '__call__'):
1506 elif hasattr(obj, '__call__'):
1499 call_obj = obj.__call__
1507 call_obj = obj.__call__
1500 ret += self._default_arguments_from_docstring(
1508 ret += self._default_arguments_from_docstring(
1501 getattr(call_obj, '__doc__', ''))
1509 getattr(call_obj, '__doc__', ''))
1502
1510
1503 _keeps = (inspect.Parameter.KEYWORD_ONLY,
1511 _keeps = (inspect.Parameter.KEYWORD_ONLY,
1504 inspect.Parameter.POSITIONAL_OR_KEYWORD)
1512 inspect.Parameter.POSITIONAL_OR_KEYWORD)
1505
1513
1506 try:
1514 try:
1507 sig = inspect.signature(call_obj)
1515 sig = inspect.signature(call_obj)
1508 ret.extend(k for k, v in sig.parameters.items() if
1516 ret.extend(k for k, v in sig.parameters.items() if
1509 v.kind in _keeps)
1517 v.kind in _keeps)
1510 except ValueError:
1518 except ValueError:
1511 pass
1519 pass
1512
1520
1513 return list(set(ret))
1521 return list(set(ret))
1514
1522
1515 def python_func_kw_matches(self,text):
1523 def python_func_kw_matches(self, text):
1516 """Match named parameters (kwargs) of the last open function"""
1524 """Match named parameters (kwargs) of the last open function"""
1517
1525
1518 if "." in text: # a parameter cannot be dotted
1526 if "." in text: # a parameter cannot be dotted
1519 return []
1527 return []
1520 try: regexp = self.__funcParamsRegex
1528 try: regexp = self.__funcParamsRegex
1521 except AttributeError:
1529 except AttributeError:
1522 regexp = self.__funcParamsRegex = re.compile(r'''
1530 regexp = self.__funcParamsRegex = re.compile(r'''
1523 '.*?(?<!\\)' | # single quoted strings or
1531 '.*?(?<!\\)' | # single quoted strings or
1524 ".*?(?<!\\)" | # double quoted strings or
1532 ".*?(?<!\\)" | # double quoted strings or
1525 \w+ | # identifier
1533 \w+ | # identifier
1526 \S # other characters
1534 \S # other characters
1527 ''', re.VERBOSE | re.DOTALL)
1535 ''', re.VERBOSE | re.DOTALL)
1528 # 1. find the nearest identifier that comes before an unclosed
1536 # 1. find the nearest identifier that comes before an unclosed
1529 # parenthesis before the cursor
1537 # parenthesis before the cursor
1530 # e.g. for "foo (1+bar(x), pa<cursor>,a=1)", the candidate is "foo"
1538 # e.g. for "foo (1+bar(x), pa<cursor>,a=1)", the candidate is "foo"
1531 tokens = regexp.findall(self.text_until_cursor)
1539 tokens = regexp.findall(self.text_until_cursor)
1532 iterTokens = reversed(tokens); openPar = 0
1540 iterTokens = reversed(tokens); openPar = 0
1533
1541
1534 for token in iterTokens:
1542 for token in iterTokens:
1535 if token == ')':
1543 if token == ')':
1536 openPar -= 1
1544 openPar -= 1
1537 elif token == '(':
1545 elif token == '(':
1538 openPar += 1
1546 openPar += 1
1539 if openPar > 0:
1547 if openPar > 0:
1540 # found the last unclosed parenthesis
1548 # found the last unclosed parenthesis
1541 break
1549 break
1542 else:
1550 else:
1543 return []
1551 return []
1544 # 2. Concatenate dotted names ("foo.bar" for "foo.bar(x, pa" )
1552 # 2. Concatenate dotted names ("foo.bar" for "foo.bar(x, pa" )
1545 ids = []
1553 ids = []
1546 isId = re.compile(r'\w+$').match
1554 isId = re.compile(r'\w+$').match
1547
1555
1548 while True:
1556 while True:
1549 try:
1557 try:
1550 ids.append(next(iterTokens))
1558 ids.append(next(iterTokens))
1551 if not isId(ids[-1]):
1559 if not isId(ids[-1]):
1552 ids.pop(); break
1560 ids.pop(); break
1553 if not next(iterTokens) == '.':
1561 if not next(iterTokens) == '.':
1554 break
1562 break
1555 except StopIteration:
1563 except StopIteration:
1556 break
1564 break
1557
1565
1558 # Find all named arguments already assigned to, as to avoid suggesting
1566 # Find all named arguments already assigned to, as to avoid suggesting
1559 # them again
1567 # them again
1560 usedNamedArgs = set()
1568 usedNamedArgs = set()
1561 par_level = -1
1569 par_level = -1
1562 for token, next_token in zip(tokens, tokens[1:]):
1570 for token, next_token in zip(tokens, tokens[1:]):
1563 if token == '(':
1571 if token == '(':
1564 par_level += 1
1572 par_level += 1
1565 elif token == ')':
1573 elif token == ')':
1566 par_level -= 1
1574 par_level -= 1
1567
1575
1568 if par_level != 0:
1576 if par_level != 0:
1569 continue
1577 continue
1570
1578
1571 if next_token != '=':
1579 if next_token != '=':
1572 continue
1580 continue
1573
1581
1574 usedNamedArgs.add(token)
1582 usedNamedArgs.add(token)
1575
1583
1576 argMatches = []
1584 argMatches = []
1577 try:
1585 try:
1578 callableObj = '.'.join(ids[::-1])
1586 callableObj = '.'.join(ids[::-1])
1579 namedArgs = self._default_arguments(eval(callableObj,
1587 namedArgs = self._default_arguments(eval(callableObj,
1580 self.namespace))
1588 self.namespace))
1581
1589
1582 # Remove used named arguments from the list, no need to show twice
1590 # Remove used named arguments from the list, no need to show twice
1583 for namedArg in set(namedArgs) - usedNamedArgs:
1591 for namedArg in set(namedArgs) - usedNamedArgs:
1584 if namedArg.startswith(text):
1592 if namedArg.startswith(text):
1585 argMatches.append(u"%s=" %namedArg)
1593 argMatches.append(u"%s=" %namedArg)
1586 except:
1594 except:
1587 pass
1595 pass
1588
1596
1589 return argMatches
1597 return argMatches
1590
1598
1591 def dict_key_matches(self, text):
1599 @staticmethod
1600 def _get_keys(obj: Any) -> List[Any]:
1601 # Objects can define their own completions by defining an
1602 # _ipy_key_completions_() method.
1603 method = get_real_method(obj, '_ipython_key_completions_')
1604 if method is not None:
1605 return method()
1606
1607 # Special case some common in-memory dict-like types
1608 if isinstance(obj, dict) or\
1609 _safe_isinstance(obj, 'pandas', 'DataFrame'):
1610 try:
1611 return list(obj.keys())
1612 except Exception:
1613 return []
1614 elif _safe_isinstance(obj, 'numpy', 'ndarray') or\
1615 _safe_isinstance(obj, 'numpy', 'void'):
1616 return obj.dtype.names or []
1617 return []
1618
1619 def dict_key_matches(self, text:str) -> List[str]:
1592 "Match string keys in a dictionary, after e.g. 'foo[' "
1620 "Match string keys in a dictionary, after e.g. 'foo[' "
1593 def get_keys(obj):
1594 # Objects can define their own completions by defining an
1595 # _ipy_key_completions_() method.
1596 method = get_real_method(obj, '_ipython_key_completions_')
1597 if method is not None:
1598 return method()
1599
1600 # Special case some common in-memory dict-like types
1601 if isinstance(obj, dict) or\
1602 _safe_isinstance(obj, 'pandas', 'DataFrame'):
1603 try:
1604 return list(obj.keys())
1605 except Exception:
1606 return []
1607 elif _safe_isinstance(obj, 'numpy', 'ndarray') or\
1608 _safe_isinstance(obj, 'numpy', 'void'):
1609 return obj.dtype.names or []
1610 return []
1611
1621
1612 try:
1622
1623 if self.__dict_key_regexps is not None:
1613 regexps = self.__dict_key_regexps
1624 regexps = self.__dict_key_regexps
1614 except AttributeError:
1625 else:
1615 dict_key_re_fmt = r'''(?x)
1626 dict_key_re_fmt = r'''(?x)
1616 ( # match dict-referring expression wrt greedy setting
1627 ( # match dict-referring expression wrt greedy setting
1617 %s
1628 %s
1618 )
1629 )
1619 \[ # open bracket
1630 \[ # open bracket
1620 \s* # and optional whitespace
1631 \s* # and optional whitespace
1621 ([uUbB]? # string prefix (r not handled)
1632 ([uUbB]? # string prefix (r not handled)
1622 (?: # unclosed string
1633 (?: # unclosed string
1623 '(?:[^']|(?<!\\)\\')*
1634 '(?:[^']|(?<!\\)\\')*
1624 |
1635 |
1625 "(?:[^"]|(?<!\\)\\")*
1636 "(?:[^"]|(?<!\\)\\")*
1626 )
1637 )
1627 )?
1638 )?
1628 $
1639 $
1629 '''
1640 '''
1630 regexps = self.__dict_key_regexps = {
1641 regexps = self.__dict_key_regexps = {
1631 False: re.compile(dict_key_re_fmt % r'''
1642 False: re.compile(dict_key_re_fmt % r'''
1632 # identifiers separated by .
1643 # identifiers separated by .
1633 (?!\d)\w+
1644 (?!\d)\w+
1634 (?:\.(?!\d)\w+)*
1645 (?:\.(?!\d)\w+)*
1635 '''),
1646 '''),
1636 True: re.compile(dict_key_re_fmt % '''
1647 True: re.compile(dict_key_re_fmt % '''
1637 .+
1648 .+
1638 ''')
1649 ''')
1639 }
1650 }
1640
1651
1641 match = regexps[self.greedy].search(self.text_until_cursor)
1652 match = regexps[self.greedy].search(self.text_until_cursor)
1642 if match is None:
1653 if match is None:
1643 return []
1654 return []
1644
1655
1645 expr, prefix = match.groups()
1656 expr, prefix = match.groups()
1646 try:
1657 try:
1647 obj = eval(expr, self.namespace)
1658 obj = eval(expr, self.namespace)
1648 except Exception:
1659 except Exception:
1649 try:
1660 try:
1650 obj = eval(expr, self.global_namespace)
1661 obj = eval(expr, self.global_namespace)
1651 except Exception:
1662 except Exception:
1652 return []
1663 return []
1653
1664
1654 keys = get_keys(obj)
1665 keys = self._get_keys(obj)
1655 if not keys:
1666 if not keys:
1656 return keys
1667 return keys
1657 closing_quote, token_offset, matches = match_dict_keys(keys, prefix, self.splitter.delims)
1668 closing_quote, token_offset, matches = match_dict_keys(keys, prefix, self.splitter.delims)
1658 if not matches:
1669 if not matches:
1659 return matches
1670 return matches
1660
1671
1661 # get the cursor position of
1672 # get the cursor position of
1662 # - the text being completed
1673 # - the text being completed
1663 # - the start of the key text
1674 # - the start of the key text
1664 # - the start of the completion
1675 # - the start of the completion
1665 text_start = len(self.text_until_cursor) - len(text)
1676 text_start = len(self.text_until_cursor) - len(text)
1666 if prefix:
1677 if prefix:
1667 key_start = match.start(2)
1678 key_start = match.start(2)
1668 completion_start = key_start + token_offset
1679 completion_start = key_start + token_offset
1669 else:
1680 else:
1670 key_start = completion_start = match.end()
1681 key_start = completion_start = match.end()
1671
1682
1672 # grab the leading prefix, to make sure all completions start with `text`
1683 # grab the leading prefix, to make sure all completions start with `text`
1673 if text_start > key_start:
1684 if text_start > key_start:
1674 leading = ''
1685 leading = ''
1675 else:
1686 else:
1676 leading = text[text_start:completion_start]
1687 leading = text[text_start:completion_start]
1677
1688
1678 # the index of the `[` character
1689 # the index of the `[` character
1679 bracket_idx = match.end(1)
1690 bracket_idx = match.end(1)
1680
1691
1681 # append closing quote and bracket as appropriate
1692 # append closing quote and bracket as appropriate
1682 # this is *not* appropriate if the opening quote or bracket is outside
1693 # this is *not* appropriate if the opening quote or bracket is outside
1683 # the text given to this method
1694 # the text given to this method
1684 suf = ''
1695 suf = ''
1685 continuation = self.line_buffer[len(self.text_until_cursor):]
1696 continuation = self.line_buffer[len(self.text_until_cursor):]
1686 if key_start > text_start and closing_quote:
1697 if key_start > text_start and closing_quote:
1687 # quotes were opened inside text, maybe close them
1698 # quotes were opened inside text, maybe close them
1688 if continuation.startswith(closing_quote):
1699 if continuation.startswith(closing_quote):
1689 continuation = continuation[len(closing_quote):]
1700 continuation = continuation[len(closing_quote):]
1690 else:
1701 else:
1691 suf += closing_quote
1702 suf += closing_quote
1692 if bracket_idx > text_start:
1703 if bracket_idx > text_start:
1693 # brackets were opened inside text, maybe close them
1704 # brackets were opened inside text, maybe close them
1694 if not continuation.startswith(']'):
1705 if not continuation.startswith(']'):
1695 suf += ']'
1706 suf += ']'
1696
1707
1697 return [leading + k + suf for k in matches]
1708 return [leading + k + suf for k in matches]
1698
1709
1699 def unicode_name_matches(self, text):
1710 @staticmethod
1700 u"""Match Latex-like syntax for unicode characters base
1711 def unicode_name_matches(text:str) -> Tuple[str, List[str]] :
1712 """Match Latex-like syntax for unicode characters base
1701 on the name of the character.
1713 on the name of the character.
1702
1714
1703 This does ``\\GREEK SMALL LETTER ETA`` -> ``Ξ·``
1715 This does ``\\GREEK SMALL LETTER ETA`` -> ``Ξ·``
1704
1716
1705 Works only on valid python 3 identifier, or on combining characters that
1717 Works only on valid python 3 identifier, or on combining characters that
1706 will combine to form a valid identifier.
1718 will combine to form a valid identifier.
1707
1708 Used on Python 3 only.
1709 """
1719 """
1710 slashpos = text.rfind('\\')
1720 slashpos = text.rfind('\\')
1711 if slashpos > -1:
1721 if slashpos > -1:
1712 s = text[slashpos+1:]
1722 s = text[slashpos+1:]
1713 try :
1723 try :
1714 unic = unicodedata.lookup(s)
1724 unic = unicodedata.lookup(s)
1715 # allow combining chars
1725 # allow combining chars
1716 if ('a'+unic).isidentifier():
1726 if ('a'+unic).isidentifier():
1717 return '\\'+s,[unic]
1727 return '\\'+s,[unic]
1718 except KeyError:
1728 except KeyError:
1719 pass
1729 pass
1720 return u'', []
1730 return '', []
1721
1731
1722
1732
1723 def latex_matches(self, text):
1733 def latex_matches(self, text):
1724 u"""Match Latex syntax for unicode characters.
1734 u"""Match Latex syntax for unicode characters.
1725
1735
1726 This does both ``\\alp`` -> ``\\alpha`` and ``\\alpha`` -> ``Ξ±``
1736 This does both ``\\alp`` -> ``\\alpha`` and ``\\alpha`` -> ``Ξ±``
1727 """
1737 """
1728 slashpos = text.rfind('\\')
1738 slashpos = text.rfind('\\')
1729 if slashpos > -1:
1739 if slashpos > -1:
1730 s = text[slashpos:]
1740 s = text[slashpos:]
1731 if s in latex_symbols:
1741 if s in latex_symbols:
1732 # Try to complete a full latex symbol to unicode
1742 # Try to complete a full latex symbol to unicode
1733 # \\alpha -> Ξ±
1743 # \\alpha -> Ξ±
1734 return s, [latex_symbols[s]]
1744 return s, [latex_symbols[s]]
1735 else:
1745 else:
1736 # If a user has partially typed a latex symbol, give them
1746 # If a user has partially typed a latex symbol, give them
1737 # a full list of options \al -> [\aleph, \alpha]
1747 # a full list of options \al -> [\aleph, \alpha]
1738 matches = [k for k in latex_symbols if k.startswith(s)]
1748 matches = [k for k in latex_symbols if k.startswith(s)]
1739 if matches:
1749 if matches:
1740 return s, matches
1750 return s, matches
1741 return u'', []
1751 return u'', []
1742
1752
1743 def dispatch_custom_completer(self, text):
1753 def dispatch_custom_completer(self, text):
1744 if not self.custom_completers:
1754 if not self.custom_completers:
1745 return
1755 return
1746
1756
1747 line = self.line_buffer
1757 line = self.line_buffer
1748 if not line.strip():
1758 if not line.strip():
1749 return None
1759 return None
1750
1760
1751 # Create a little structure to pass all the relevant information about
1761 # Create a little structure to pass all the relevant information about
1752 # the current completion to any custom completer.
1762 # the current completion to any custom completer.
1753 event = SimpleNamespace()
1763 event = SimpleNamespace()
1754 event.line = line
1764 event.line = line
1755 event.symbol = text
1765 event.symbol = text
1756 cmd = line.split(None,1)[0]
1766 cmd = line.split(None,1)[0]
1757 event.command = cmd
1767 event.command = cmd
1758 event.text_until_cursor = self.text_until_cursor
1768 event.text_until_cursor = self.text_until_cursor
1759
1769
1760 # for foo etc, try also to find completer for %foo
1770 # for foo etc, try also to find completer for %foo
1761 if not cmd.startswith(self.magic_escape):
1771 if not cmd.startswith(self.magic_escape):
1762 try_magic = self.custom_completers.s_matches(
1772 try_magic = self.custom_completers.s_matches(
1763 self.magic_escape + cmd)
1773 self.magic_escape + cmd)
1764 else:
1774 else:
1765 try_magic = []
1775 try_magic = []
1766
1776
1767 for c in itertools.chain(self.custom_completers.s_matches(cmd),
1777 for c in itertools.chain(self.custom_completers.s_matches(cmd),
1768 try_magic,
1778 try_magic,
1769 self.custom_completers.flat_matches(self.text_until_cursor)):
1779 self.custom_completers.flat_matches(self.text_until_cursor)):
1770 try:
1780 try:
1771 res = c(event)
1781 res = c(event)
1772 if res:
1782 if res:
1773 # first, try case sensitive match
1783 # first, try case sensitive match
1774 withcase = [r for r in res if r.startswith(text)]
1784 withcase = [r for r in res if r.startswith(text)]
1775 if withcase:
1785 if withcase:
1776 return withcase
1786 return withcase
1777 # if none, then case insensitive ones are ok too
1787 # if none, then case insensitive ones are ok too
1778 text_low = text.lower()
1788 text_low = text.lower()
1779 return [r for r in res if r.lower().startswith(text_low)]
1789 return [r for r in res if r.lower().startswith(text_low)]
1780 except TryNext:
1790 except TryNext:
1781 pass
1791 pass
1782 except KeyboardInterrupt:
1792 except KeyboardInterrupt:
1783 """
1793 """
1784 If custom completer take too long,
1794 If custom completer take too long,
1785 let keyboard interrupt abort and return nothing.
1795 let keyboard interrupt abort and return nothing.
1786 """
1796 """
1787 break
1797 break
1788
1798
1789 return None
1799 return None
1790
1800
1791 def completions(self, text: str, offset: int)->Iterator[Completion]:
1801 def completions(self, text: str, offset: int)->Iterator[Completion]:
1792 """
1802 """
1793 Returns an iterator over the possible completions
1803 Returns an iterator over the possible completions
1794
1804
1795 .. warning:: Unstable
1805 .. warning:: Unstable
1796
1806
1797 This function is unstable, API may change without warning.
1807 This function is unstable, API may change without warning.
1798 It will also raise unless use in proper context manager.
1808 It will also raise unless use in proper context manager.
1799
1809
1800 Parameters
1810 Parameters
1801 ----------
1811 ----------
1802
1812
1803 text:str
1813 text:str
1804 Full text of the current input, multi line string.
1814 Full text of the current input, multi line string.
1805 offset:int
1815 offset:int
1806 Integer representing the position of the cursor in ``text``. Offset
1816 Integer representing the position of the cursor in ``text``. Offset
1807 is 0-based indexed.
1817 is 0-based indexed.
1808
1818
1809 Yields
1819 Yields
1810 ------
1820 ------
1811 :any:`Completion` object
1821 :any:`Completion` object
1812
1822
1813
1823
1814 The cursor on a text can either be seen as being "in between"
1824 The cursor on a text can either be seen as being "in between"
1815 characters or "On" a character depending on the interface visible to
1825 characters or "On" a character depending on the interface visible to
1816 the user. For consistency the cursor being on "in between" characters X
1826 the user. For consistency the cursor being on "in between" characters X
1817 and Y is equivalent to the cursor being "on" character Y, that is to say
1827 and Y is equivalent to the cursor being "on" character Y, that is to say
1818 the character the cursor is on is considered as being after the cursor.
1828 the character the cursor is on is considered as being after the cursor.
1819
1829
1820 Combining characters may span more that one position in the
1830 Combining characters may span more that one position in the
1821 text.
1831 text.
1822
1832
1823
1833
1824 .. note::
1834 .. note::
1825
1835
1826 If ``IPCompleter.debug`` is :any:`True` will yield a ``--jedi/ipython--``
1836 If ``IPCompleter.debug`` is :any:`True` will yield a ``--jedi/ipython--``
1827 fake Completion token to distinguish completion returned by Jedi
1837 fake Completion token to distinguish completion returned by Jedi
1828 and usual IPython completion.
1838 and usual IPython completion.
1829
1839
1830 .. note::
1840 .. note::
1831
1841
1832 Completions are not completely deduplicated yet. If identical
1842 Completions are not completely deduplicated yet. If identical
1833 completions are coming from different sources this function does not
1843 completions are coming from different sources this function does not
1834 ensure that each completion object will only be present once.
1844 ensure that each completion object will only be present once.
1835 """
1845 """
1836 warnings.warn("_complete is a provisional API (as of IPython 6.0). "
1846 warnings.warn("_complete is a provisional API (as of IPython 6.0). "
1837 "It may change without warnings. "
1847 "It may change without warnings. "
1838 "Use in corresponding context manager.",
1848 "Use in corresponding context manager.",
1839 category=ProvisionalCompleterWarning, stacklevel=2)
1849 category=ProvisionalCompleterWarning, stacklevel=2)
1840
1850
1841 seen = set()
1851 seen = set()
1852 profiler:Optional[cProfile.Profile]
1842 try:
1853 try:
1843 if self.profile_completions:
1854 if self.profile_completions:
1844 import cProfile
1855 import cProfile
1845 profiler = cProfile.Profile()
1856 profiler = cProfile.Profile()
1846 profiler.enable()
1857 profiler.enable()
1847 else:
1858 else:
1848 profiler = None
1859 profiler = None
1849
1860
1850 for c in self._completions(text, offset, _timeout=self.jedi_compute_type_timeout/1000):
1861 for c in self._completions(text, offset, _timeout=self.jedi_compute_type_timeout/1000):
1851 if c and (c in seen):
1862 if c and (c in seen):
1852 continue
1863 continue
1853 yield c
1864 yield c
1854 seen.add(c)
1865 seen.add(c)
1855 except KeyboardInterrupt:
1866 except KeyboardInterrupt:
1856 """if completions take too long and users send keyboard interrupt,
1867 """if completions take too long and users send keyboard interrupt,
1857 do not crash and return ASAP. """
1868 do not crash and return ASAP. """
1858 pass
1869 pass
1859 finally:
1870 finally:
1860 if profiler is not None:
1871 if profiler is not None:
1861 profiler.disable()
1872 profiler.disable()
1862 ensure_dir_exists(self.profiler_output_dir)
1873 ensure_dir_exists(self.profiler_output_dir)
1863 output_path = os.path.join(self.profiler_output_dir, str(uuid.uuid4()))
1874 output_path = os.path.join(self.profiler_output_dir, str(uuid.uuid4()))
1864 print("Writing profiler output to", output_path)
1875 print("Writing profiler output to", output_path)
1865 profiler.dump_stats(output_path)
1876 profiler.dump_stats(output_path)
1866
1877
1867 def _completions(self, full_text: str, offset: int, *, _timeout)->Iterator[Completion]:
1878 def _completions(self, full_text: str, offset: int, *, _timeout) -> Iterator[Completion]:
1868 """
1879 """
1869 Core completion module.Same signature as :any:`completions`, with the
1880 Core completion module.Same signature as :any:`completions`, with the
1870 extra `timeout` parameter (in seconds).
1881 extra `timeout` parameter (in seconds).
1871
1882
1872
1883
1873 Computing jedi's completion ``.type`` can be quite expensive (it is a
1884 Computing jedi's completion ``.type`` can be quite expensive (it is a
1874 lazy property) and can require some warm-up, more warm up than just
1885 lazy property) and can require some warm-up, more warm up than just
1875 computing the ``name`` of a completion. The warm-up can be :
1886 computing the ``name`` of a completion. The warm-up can be :
1876
1887
1877 - Long warm-up the first time a module is encountered after
1888 - Long warm-up the first time a module is encountered after
1878 install/update: actually build parse/inference tree.
1889 install/update: actually build parse/inference tree.
1879
1890
1880 - first time the module is encountered in a session: load tree from
1891 - first time the module is encountered in a session: load tree from
1881 disk.
1892 disk.
1882
1893
1883 We don't want to block completions for tens of seconds so we give the
1894 We don't want to block completions for tens of seconds so we give the
1884 completer a "budget" of ``_timeout`` seconds per invocation to compute
1895 completer a "budget" of ``_timeout`` seconds per invocation to compute
1885 completions types, the completions that have not yet been computed will
1896 completions types, the completions that have not yet been computed will
1886 be marked as "unknown" an will have a chance to be computed next round
1897 be marked as "unknown" an will have a chance to be computed next round
1887 are things get cached.
1898 are things get cached.
1888
1899
1889 Keep in mind that Jedi is not the only thing treating the completion so
1900 Keep in mind that Jedi is not the only thing treating the completion so
1890 keep the timeout short-ish as if we take more than 0.3 second we still
1901 keep the timeout short-ish as if we take more than 0.3 second we still
1891 have lots of processing to do.
1902 have lots of processing to do.
1892
1903
1893 """
1904 """
1894 deadline = time.monotonic() + _timeout
1905 deadline = time.monotonic() + _timeout
1895
1906
1896
1907
1897 before = full_text[:offset]
1908 before = full_text[:offset]
1898 cursor_line, cursor_column = position_to_cursor(full_text, offset)
1909 cursor_line, cursor_column = position_to_cursor(full_text, offset)
1899
1910
1900 matched_text, matches, matches_origin, jedi_matches = self._complete(
1911 matched_text, matches, matches_origin, jedi_matches = self._complete(
1901 full_text=full_text, cursor_line=cursor_line, cursor_pos=cursor_column)
1912 full_text=full_text, cursor_line=cursor_line, cursor_pos=cursor_column)
1902
1913
1903 iter_jm = iter(jedi_matches)
1914 iter_jm = iter(jedi_matches)
1904 if _timeout:
1915 if _timeout:
1905 for jm in iter_jm:
1916 for jm in iter_jm:
1906 try:
1917 try:
1907 type_ = jm.type
1918 type_ = jm.type
1908 except Exception:
1919 except Exception:
1909 if self.debug:
1920 if self.debug:
1910 print("Error in Jedi getting type of ", jm)
1921 print("Error in Jedi getting type of ", jm)
1911 type_ = None
1922 type_ = None
1912 delta = len(jm.name_with_symbols) - len(jm.complete)
1923 delta = len(jm.name_with_symbols) - len(jm.complete)
1913 if type_ == 'function':
1924 if type_ == 'function':
1914 signature = _make_signature(jm)
1925 signature = _make_signature(jm)
1915 else:
1926 else:
1916 signature = ''
1927 signature = ''
1917 yield Completion(start=offset - delta,
1928 yield Completion(start=offset - delta,
1918 end=offset,
1929 end=offset,
1919 text=jm.name_with_symbols,
1930 text=jm.name_with_symbols,
1920 type=type_,
1931 type=type_,
1921 signature=signature,
1932 signature=signature,
1922 _origin='jedi')
1933 _origin='jedi')
1923
1934
1924 if time.monotonic() > deadline:
1935 if time.monotonic() > deadline:
1925 break
1936 break
1926
1937
1927 for jm in iter_jm:
1938 for jm in iter_jm:
1928 delta = len(jm.name_with_symbols) - len(jm.complete)
1939 delta = len(jm.name_with_symbols) - len(jm.complete)
1929 yield Completion(start=offset - delta,
1940 yield Completion(start=offset - delta,
1930 end=offset,
1941 end=offset,
1931 text=jm.name_with_symbols,
1942 text=jm.name_with_symbols,
1932 type='<unknown>', # don't compute type for speed
1943 type='<unknown>', # don't compute type for speed
1933 _origin='jedi',
1944 _origin='jedi',
1934 signature='')
1945 signature='')
1935
1946
1936
1947
1937 start_offset = before.rfind(matched_text)
1948 start_offset = before.rfind(matched_text)
1938
1949
1939 # TODO:
1950 # TODO:
1940 # Suppress this, right now just for debug.
1951 # Suppress this, right now just for debug.
1941 if jedi_matches and matches and self.debug:
1952 if jedi_matches and matches and self.debug:
1942 yield Completion(start=start_offset, end=offset, text='--jedi/ipython--',
1953 yield Completion(start=start_offset, end=offset, text='--jedi/ipython--',
1943 _origin='debug', type='none', signature='')
1954 _origin='debug', type='none', signature='')
1944
1955
1945 # I'm unsure if this is always true, so let's assert and see if it
1956 # I'm unsure if this is always true, so let's assert and see if it
1946 # crash
1957 # crash
1947 assert before.endswith(matched_text)
1958 assert before.endswith(matched_text)
1948 for m, t in zip(matches, matches_origin):
1959 for m, t in zip(matches, matches_origin):
1949 yield Completion(start=start_offset, end=offset, text=m, _origin=t, signature='', type='<unknown>')
1960 yield Completion(start=start_offset, end=offset, text=m, _origin=t, signature='', type='<unknown>')
1950
1961
1951
1962
1952 def complete(self, text=None, line_buffer=None, cursor_pos=None):
1963 def complete(self, text=None, line_buffer=None, cursor_pos=None) -> Tuple[str, Sequence[str]]:
1953 """Find completions for the given text and line context.
1964 """Find completions for the given text and line context.
1954
1965
1955 Note that both the text and the line_buffer are optional, but at least
1966 Note that both the text and the line_buffer are optional, but at least
1956 one of them must be given.
1967 one of them must be given.
1957
1968
1958 Parameters
1969 Parameters
1959 ----------
1970 ----------
1960 text : string, optional
1971 text : string, optional
1961 Text to perform the completion on. If not given, the line buffer
1972 Text to perform the completion on. If not given, the line buffer
1962 is split using the instance's CompletionSplitter object.
1973 is split using the instance's CompletionSplitter object.
1963
1974
1964 line_buffer : string, optional
1975 line_buffer : string, optional
1965 If not given, the completer attempts to obtain the current line
1976 If not given, the completer attempts to obtain the current line
1966 buffer via readline. This keyword allows clients which are
1977 buffer via readline. This keyword allows clients which are
1967 requesting for text completions in non-readline contexts to inform
1978 requesting for text completions in non-readline contexts to inform
1968 the completer of the entire text.
1979 the completer of the entire text.
1969
1980
1970 cursor_pos : int, optional
1981 cursor_pos : int, optional
1971 Index of the cursor in the full line buffer. Should be provided by
1982 Index of the cursor in the full line buffer. Should be provided by
1972 remote frontends where kernel has no access to frontend state.
1983 remote frontends where kernel has no access to frontend state.
1973
1984
1974 Returns
1985 Returns
1975 -------
1986 -------
1987 Tuple of two items:
1976 text : str
1988 text : str
1977 Text that was actually used in the completion.
1989 Text that was actually used in the completion.
1978
1979 matches : list
1990 matches : list
1980 A list of completion matches.
1991 A list of completion matches.
1981
1992
1982
1993
1983 .. note::
1994 .. note::
1984
1995
1985 This API is likely to be deprecated and replaced by
1996 This API is likely to be deprecated and replaced by
1986 :any:`IPCompleter.completions` in the future.
1997 :any:`IPCompleter.completions` in the future.
1987
1998
1988
1999
1989 """
2000 """
1990 warnings.warn('`Completer.complete` is pending deprecation since '
2001 warnings.warn('`Completer.complete` is pending deprecation since '
1991 'IPython 6.0 and will be replaced by `Completer.completions`.',
2002 'IPython 6.0 and will be replaced by `Completer.completions`.',
1992 PendingDeprecationWarning)
2003 PendingDeprecationWarning)
1993 # potential todo, FOLD the 3rd throw away argument of _complete
2004 # potential todo, FOLD the 3rd throw away argument of _complete
1994 # into the first 2 one.
2005 # into the first 2 one.
1995 return self._complete(line_buffer=line_buffer, cursor_pos=cursor_pos, text=text, cursor_line=0)[:2]
2006 return self._complete(line_buffer=line_buffer, cursor_pos=cursor_pos, text=text, cursor_line=0)[:2]
1996
2007
1997 def _complete(self, *, cursor_line, cursor_pos, line_buffer=None, text=None,
2008 def _complete(self, *, cursor_line, cursor_pos, line_buffer=None, text=None,
1998 full_text=None) -> Tuple[str, List[str], List[str], Iterable[_FakeJediCompletion]]:
2009 full_text=None) -> _CompleteResult:
1999 """
2010 """
2000
2011
2001 Like complete but can also returns raw jedi completions as well as the
2012 Like complete but can also returns raw jedi completions as well as the
2002 origin of the completion text. This could (and should) be made much
2013 origin of the completion text. This could (and should) be made much
2003 cleaner but that will be simpler once we drop the old (and stateful)
2014 cleaner but that will be simpler once we drop the old (and stateful)
2004 :any:`complete` API.
2015 :any:`complete` API.
2005
2016
2006
2017
2007 With current provisional API, cursor_pos act both (depending on the
2018 With current provisional API, cursor_pos act both (depending on the
2008 caller) as the offset in the ``text`` or ``line_buffer``, or as the
2019 caller) as the offset in the ``text`` or ``line_buffer``, or as the
2009 ``column`` when passing multiline strings this could/should be renamed
2020 ``column`` when passing multiline strings this could/should be renamed
2010 but would add extra noise.
2021 but would add extra noise.
2022
2023 Return
2024 ======
2025
2026 A tuple of N elements which are (likely):
2027
2028 matched_text: ? the text that the complete matched
2029 matches: list of completions ?
2030 matches_origin: ? list same lenght as matches, and where each completion came from
2031 jedi_matches: list of Jedi matches, have it's own structure.
2011 """
2032 """
2012
2033
2034
2013 # if the cursor position isn't given, the only sane assumption we can
2035 # if the cursor position isn't given, the only sane assumption we can
2014 # make is that it's at the end of the line (the common case)
2036 # make is that it's at the end of the line (the common case)
2015 if cursor_pos is None:
2037 if cursor_pos is None:
2016 cursor_pos = len(line_buffer) if text is None else len(text)
2038 cursor_pos = len(line_buffer) if text is None else len(text)
2017
2039
2018 if self.use_main_ns:
2040 if self.use_main_ns:
2019 self.namespace = __main__.__dict__
2041 self.namespace = __main__.__dict__
2020
2042
2021 # if text is either None or an empty string, rely on the line buffer
2043 # if text is either None or an empty string, rely on the line buffer
2022 if (not line_buffer) and full_text:
2044 if (not line_buffer) and full_text:
2023 line_buffer = full_text.split('\n')[cursor_line]
2045 line_buffer = full_text.split('\n')[cursor_line]
2024 if not text:
2046 if not text:
2025 text = self.splitter.split_line(line_buffer, cursor_pos)
2047 text = self.splitter.split_line(line_buffer, cursor_pos)
2026
2048
2027 if self.backslash_combining_completions:
2049 if self.backslash_combining_completions:
2028 # allow deactivation of these on windows.
2050 # allow deactivation of these on windows.
2029 base_text = text if not line_buffer else line_buffer[:cursor_pos]
2051 base_text = text if not line_buffer else line_buffer[:cursor_pos]
2030 latex_text, latex_matches = self.latex_matches(base_text)
2052
2031 if latex_matches:
2053 for meth in (self.latex_matches,
2032 return latex_text, latex_matches, ['latex_matches']*len(latex_matches), ()
2054 self.unicode_name_matches,
2033 name_text = ''
2055 back_latex_name_matches,
2034 name_matches = []
2056 back_unicode_name_matches,
2035 # need to add self.fwd_unicode_match() function here when done
2057 self.fwd_unicode_match):
2036 for meth in (self.unicode_name_matches, back_latex_name_matches, back_unicode_name_matches, self.fwd_unicode_match):
2037 name_text, name_matches = meth(base_text)
2058 name_text, name_matches = meth(base_text)
2038 if name_text:
2059 if name_text:
2039 return name_text, name_matches[:MATCHES_LIMIT], \
2060 return _CompleteResult(name_text, name_matches[:MATCHES_LIMIT], \
2040 [meth.__qualname__]*min(len(name_matches), MATCHES_LIMIT), ()
2061 [meth.__qualname__]*min(len(name_matches), MATCHES_LIMIT), ())
2041
2062
2042
2063
2043 # If no line buffer is given, assume the input text is all there was
2064 # If no line buffer is given, assume the input text is all there was
2044 if line_buffer is None:
2065 if line_buffer is None:
2045 line_buffer = text
2066 line_buffer = text
2046
2067
2047 self.line_buffer = line_buffer
2068 self.line_buffer = line_buffer
2048 self.text_until_cursor = self.line_buffer[:cursor_pos]
2069 self.text_until_cursor = self.line_buffer[:cursor_pos]
2049
2070
2050 # Do magic arg matches
2071 # Do magic arg matches
2051 for matcher in self.magic_arg_matchers:
2072 for matcher in self.magic_arg_matchers:
2052 matches = list(matcher(line_buffer))[:MATCHES_LIMIT]
2073 matches = list(matcher(line_buffer))[:MATCHES_LIMIT]
2053 if matches:
2074 if matches:
2054 origins = [matcher.__qualname__] * len(matches)
2075 origins = [matcher.__qualname__] * len(matches)
2055 return text, matches, origins, ()
2076 return _CompleteResult(text, matches, origins, ())
2056
2077
2057 # Start with a clean slate of completions
2078 # Start with a clean slate of completions
2058 matches = []
2079 matches = []
2059
2080
2060 # FIXME: we should extend our api to return a dict with completions for
2081 # FIXME: we should extend our api to return a dict with completions for
2061 # different types of objects. The rlcomplete() method could then
2082 # different types of objects. The rlcomplete() method could then
2062 # simply collapse the dict into a list for readline, but we'd have
2083 # simply collapse the dict into a list for readline, but we'd have
2063 # richer completion semantics in other environments.
2084 # richer completion semantics in other environments.
2064 completions = ()
2085 completions:Iterable[Any] = []
2065 if self.use_jedi:
2086 if self.use_jedi:
2066 if not full_text:
2087 if not full_text:
2067 full_text = line_buffer
2088 full_text = line_buffer
2068 completions = self._jedi_matches(
2089 completions = self._jedi_matches(
2069 cursor_pos, cursor_line, full_text)
2090 cursor_pos, cursor_line, full_text)
2070
2091
2071 if self.merge_completions:
2092 if self.merge_completions:
2072 matches = []
2093 matches = []
2073 for matcher in self.matchers:
2094 for matcher in self.matchers:
2074 try:
2095 try:
2075 matches.extend([(m, matcher.__qualname__)
2096 matches.extend([(m, matcher.__qualname__)
2076 for m in matcher(text)])
2097 for m in matcher(text)])
2077 except:
2098 except:
2078 # Show the ugly traceback if the matcher causes an
2099 # Show the ugly traceback if the matcher causes an
2079 # exception, but do NOT crash the kernel!
2100 # exception, but do NOT crash the kernel!
2080 sys.excepthook(*sys.exc_info())
2101 sys.excepthook(*sys.exc_info())
2081 else:
2102 else:
2082 for matcher in self.matchers:
2103 for matcher in self.matchers:
2083 matches = [(m, matcher.__qualname__)
2104 matches = [(m, matcher.__qualname__)
2084 for m in matcher(text)]
2105 for m in matcher(text)]
2085 if matches:
2106 if matches:
2086 break
2107 break
2087
2108
2088 seen = set()
2109 seen = set()
2089 filtered_matches = set()
2110 filtered_matches = set()
2090 for m in matches:
2111 for m in matches:
2091 t, c = m
2112 t, c = m
2092 if t not in seen:
2113 if t not in seen:
2093 filtered_matches.add(m)
2114 filtered_matches.add(m)
2094 seen.add(t)
2115 seen.add(t)
2095
2116
2096 _filtered_matches = sorted(filtered_matches, key=lambda x: completions_sorting_key(x[0]))
2117 _filtered_matches = sorted(filtered_matches, key=lambda x: completions_sorting_key(x[0]))
2097
2118
2098 custom_res = [(m, 'custom') for m in self.dispatch_custom_completer(text) or []]
2119 custom_res = [(m, 'custom') for m in self.dispatch_custom_completer(text) or []]
2099
2120
2100 _filtered_matches = custom_res or _filtered_matches
2121 _filtered_matches = custom_res or _filtered_matches
2101
2122
2102 _filtered_matches = _filtered_matches[:MATCHES_LIMIT]
2123 _filtered_matches = _filtered_matches[:MATCHES_LIMIT]
2103 _matches = [m[0] for m in _filtered_matches]
2124 _matches = [m[0] for m in _filtered_matches]
2104 origins = [m[1] for m in _filtered_matches]
2125 origins = [m[1] for m in _filtered_matches]
2105
2126
2106 self.matches = _matches
2127 self.matches = _matches
2107
2128
2108 return text, _matches, origins, completions
2129 return _CompleteResult(text, _matches, origins, completions)
2109
2130
2110 def fwd_unicode_match(self, text:str) -> Tuple[str, list]:
2131 def fwd_unicode_match(self, text:str) -> Tuple[str, Iterable[str]]:
2132 """
2133
2134 Forward match a string starting with a backslash with a list of
2135 potential Unicode completions.
2136
2137 Will compute list list of Unicode character names on first call and cache it.
2138
2139 Return
2140 ======
2141
2142 At tuple with:
2143 - matched text (empty if no matches)
2144 - list of potential completions, empty tuple otherwise)
2145 """
2146 # TODO: self.unicode_names is here a list we traverse each time with ~100k elements.
2147 # We could do a faster match using a Trie.
2148
2149 # Using pygtrie the follwing seem to work:
2150
2151 # s = PrefixSet()
2152
2153 # for c in range(0,0x10FFFF + 1):
2154 # try:
2155 # s.add(unicodedata.name(chr(c)))
2156 # except ValueError:
2157 # pass
2158 # [''.join(k) for k in s.iter(prefix)]
2159
2160 # But need to be timed and adds an extra dependency.
2111
2161
2112 slashpos = text.rfind('\\')
2162 slashpos = text.rfind('\\')
2113 # if text starts with slash
2163 # if text starts with slash
2114 if slashpos > -1:
2164 if slashpos > -1:
2115 # PERF: It's important that we don't access self._unicode_names
2165 # PERF: It's important that we don't access self._unicode_names
2116 # until we're inside this if-block. _unicode_names is lazily
2166 # until we're inside this if-block. _unicode_names is lazily
2117 # initialized, and it takes a user-noticeable amount of time to
2167 # initialized, and it takes a user-noticeable amount of time to
2118 # initialize it, so we don't want to initialize it unless we're
2168 # initialize it, so we don't want to initialize it unless we're
2119 # actually going to use it.
2169 # actually going to use it.
2120 s = text[slashpos+1:]
2170 s = text[slashpos+1:]
2121 candidates = [x for x in self.unicode_names if x.startswith(s)]
2171 candidates = [x for x in self.unicode_names if x.startswith(s)]
2122 if candidates:
2172 if candidates:
2123 return s, candidates
2173 return s, candidates
2124 else:
2174 else:
2125 return '', ()
2175 return '', ()
2126
2176
2127 # if text does not start with slash
2177 # if text does not start with slash
2128 else:
2178 else:
2129 return u'', ()
2179 return '', ()
2130
2180
2131 @property
2181 @property
2132 def unicode_names(self) -> List[str]:
2182 def unicode_names(self) -> List[str]:
2133 """List of names of unicode code points that can be completed.
2183 """List of names of unicode code points that can be completed.
2134
2184
2135 The list is lazily initialized on first access.
2185 The list is lazily initialized on first access.
2136 """
2186 """
2137 if self._unicode_names is None:
2187 if self._unicode_names is None:
2138 names = []
2188 names = []
2139 for c in range(0,0x10FFFF + 1):
2189 for c in range(0,0x10FFFF + 1):
2140 try:
2190 try:
2141 names.append(unicodedata.name(chr(c)))
2191 names.append(unicodedata.name(chr(c)))
2142 except ValueError:
2192 except ValueError:
2143 pass
2193 pass
2144 self._unicode_names = names
2194 self._unicode_names = names
2145
2195
2146 return self._unicode_names
2196 return self._unicode_names
@@ -1,1111 +1,1110 b''
1 # encoding: utf-8
1 # encoding: utf-8
2 """Tests for the IPython tab-completion machinery."""
2 """Tests for the IPython tab-completion machinery."""
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 import os
7 import os
8 import sys
8 import sys
9 import textwrap
9 import textwrap
10 import unittest
10 import unittest
11
11
12 from contextlib import contextmanager
12 from contextlib import contextmanager
13
13
14 import nose.tools as nt
14 import nose.tools as nt
15
15
16 from traitlets.config.loader import Config
16 from traitlets.config.loader import Config
17 from IPython import get_ipython
17 from IPython import get_ipython
18 from IPython.core import completer
18 from IPython.core import completer
19 from IPython.external import decorators
19 from IPython.external import decorators
20 from IPython.utils.tempdir import TemporaryDirectory, TemporaryWorkingDirectory
20 from IPython.utils.tempdir import TemporaryDirectory, TemporaryWorkingDirectory
21 from IPython.utils.generics import complete_object
21 from IPython.utils.generics import complete_object
22 from IPython.testing import decorators as dec
22 from IPython.testing import decorators as dec
23
23
24 from IPython.core.completer import (
24 from IPython.core.completer import (
25 Completion,
25 Completion,
26 provisionalcompleter,
26 provisionalcompleter,
27 match_dict_keys,
27 match_dict_keys,
28 _deduplicate_completions,
28 _deduplicate_completions,
29 )
29 )
30 from nose.tools import assert_in, assert_not_in
30 from nose.tools import assert_in, assert_not_in
31
31
32 # -----------------------------------------------------------------------------
32 # -----------------------------------------------------------------------------
33 # Test functions
33 # Test functions
34 # -----------------------------------------------------------------------------
34 # -----------------------------------------------------------------------------
35
35
36
36
37 @contextmanager
37 @contextmanager
38 def greedy_completion():
38 def greedy_completion():
39 ip = get_ipython()
39 ip = get_ipython()
40 greedy_original = ip.Completer.greedy
40 greedy_original = ip.Completer.greedy
41 try:
41 try:
42 ip.Completer.greedy = True
42 ip.Completer.greedy = True
43 yield
43 yield
44 finally:
44 finally:
45 ip.Completer.greedy = greedy_original
45 ip.Completer.greedy = greedy_original
46
46
47
47
48 def test_protect_filename():
48 def test_protect_filename():
49 if sys.platform == "win32":
49 if sys.platform == "win32":
50 pairs = [
50 pairs = [
51 ("abc", "abc"),
51 ("abc", "abc"),
52 (" abc", '" abc"'),
52 (" abc", '" abc"'),
53 ("a bc", '"a bc"'),
53 ("a bc", '"a bc"'),
54 ("a bc", '"a bc"'),
54 ("a bc", '"a bc"'),
55 (" bc", '" bc"'),
55 (" bc", '" bc"'),
56 ]
56 ]
57 else:
57 else:
58 pairs = [
58 pairs = [
59 ("abc", "abc"),
59 ("abc", "abc"),
60 (" abc", r"\ abc"),
60 (" abc", r"\ abc"),
61 ("a bc", r"a\ bc"),
61 ("a bc", r"a\ bc"),
62 ("a bc", r"a\ \ bc"),
62 ("a bc", r"a\ \ bc"),
63 (" bc", r"\ \ bc"),
63 (" bc", r"\ \ bc"),
64 # On posix, we also protect parens and other special characters.
64 # On posix, we also protect parens and other special characters.
65 ("a(bc", r"a\(bc"),
65 ("a(bc", r"a\(bc"),
66 ("a)bc", r"a\)bc"),
66 ("a)bc", r"a\)bc"),
67 ("a( )bc", r"a\(\ \)bc"),
67 ("a( )bc", r"a\(\ \)bc"),
68 ("a[1]bc", r"a\[1\]bc"),
68 ("a[1]bc", r"a\[1\]bc"),
69 ("a{1}bc", r"a\{1\}bc"),
69 ("a{1}bc", r"a\{1\}bc"),
70 ("a#bc", r"a\#bc"),
70 ("a#bc", r"a\#bc"),
71 ("a?bc", r"a\?bc"),
71 ("a?bc", r"a\?bc"),
72 ("a=bc", r"a\=bc"),
72 ("a=bc", r"a\=bc"),
73 ("a\\bc", r"a\\bc"),
73 ("a\\bc", r"a\\bc"),
74 ("a|bc", r"a\|bc"),
74 ("a|bc", r"a\|bc"),
75 ("a;bc", r"a\;bc"),
75 ("a;bc", r"a\;bc"),
76 ("a:bc", r"a\:bc"),
76 ("a:bc", r"a\:bc"),
77 ("a'bc", r"a\'bc"),
77 ("a'bc", r"a\'bc"),
78 ("a*bc", r"a\*bc"),
78 ("a*bc", r"a\*bc"),
79 ('a"bc', r"a\"bc"),
79 ('a"bc', r"a\"bc"),
80 ("a^bc", r"a\^bc"),
80 ("a^bc", r"a\^bc"),
81 ("a&bc", r"a\&bc"),
81 ("a&bc", r"a\&bc"),
82 ]
82 ]
83 # run the actual tests
83 # run the actual tests
84 for s1, s2 in pairs:
84 for s1, s2 in pairs:
85 s1p = completer.protect_filename(s1)
85 s1p = completer.protect_filename(s1)
86 nt.assert_equal(s1p, s2)
86 nt.assert_equal(s1p, s2)
87
87
88
88
89 def check_line_split(splitter, test_specs):
89 def check_line_split(splitter, test_specs):
90 for part1, part2, split in test_specs:
90 for part1, part2, split in test_specs:
91 cursor_pos = len(part1)
91 cursor_pos = len(part1)
92 line = part1 + part2
92 line = part1 + part2
93 out = splitter.split_line(line, cursor_pos)
93 out = splitter.split_line(line, cursor_pos)
94 nt.assert_equal(out, split)
94 nt.assert_equal(out, split)
95
95
96
96
97 def test_line_split():
97 def test_line_split():
98 """Basic line splitter test with default specs."""
98 """Basic line splitter test with default specs."""
99 sp = completer.CompletionSplitter()
99 sp = completer.CompletionSplitter()
100 # The format of the test specs is: part1, part2, expected answer. Parts 1
100 # The format of the test specs is: part1, part2, expected answer. Parts 1
101 # and 2 are joined into the 'line' sent to the splitter, as if the cursor
101 # and 2 are joined into the 'line' sent to the splitter, as if the cursor
102 # was at the end of part1. So an empty part2 represents someone hitting
102 # was at the end of part1. So an empty part2 represents someone hitting
103 # tab at the end of the line, the most common case.
103 # tab at the end of the line, the most common case.
104 t = [
104 t = [
105 ("run some/scrip", "", "some/scrip"),
105 ("run some/scrip", "", "some/scrip"),
106 ("run scripts/er", "ror.py foo", "scripts/er"),
106 ("run scripts/er", "ror.py foo", "scripts/er"),
107 ("echo $HOM", "", "HOM"),
107 ("echo $HOM", "", "HOM"),
108 ("print sys.pa", "", "sys.pa"),
108 ("print sys.pa", "", "sys.pa"),
109 ("print(sys.pa", "", "sys.pa"),
109 ("print(sys.pa", "", "sys.pa"),
110 ("execfile('scripts/er", "", "scripts/er"),
110 ("execfile('scripts/er", "", "scripts/er"),
111 ("a[x.", "", "x."),
111 ("a[x.", "", "x."),
112 ("a[x.", "y", "x."),
112 ("a[x.", "y", "x."),
113 ('cd "some_file/', "", "some_file/"),
113 ('cd "some_file/', "", "some_file/"),
114 ]
114 ]
115 check_line_split(sp, t)
115 check_line_split(sp, t)
116 # Ensure splitting works OK with unicode by re-running the tests with
116 # Ensure splitting works OK with unicode by re-running the tests with
117 # all inputs turned into unicode
117 # all inputs turned into unicode
118 check_line_split(sp, [map(str, p) for p in t])
118 check_line_split(sp, [map(str, p) for p in t])
119
119
120
120
121 class NamedInstanceMetaclass(type):
121 class NamedInstanceMetaclass(type):
122 def __getitem__(cls, item):
122 def __getitem__(cls, item):
123 return cls.get_instance(item)
123 return cls.get_instance(item)
124
124
125
125
126 class NamedInstanceClass(metaclass=NamedInstanceMetaclass):
126 class NamedInstanceClass(metaclass=NamedInstanceMetaclass):
127 def __init__(self, name):
127 def __init__(self, name):
128 if not hasattr(self.__class__, "instances"):
128 if not hasattr(self.__class__, "instances"):
129 self.__class__.instances = {}
129 self.__class__.instances = {}
130 self.__class__.instances[name] = self
130 self.__class__.instances[name] = self
131
131
132 @classmethod
132 @classmethod
133 def _ipython_key_completions_(cls):
133 def _ipython_key_completions_(cls):
134 return cls.instances.keys()
134 return cls.instances.keys()
135
135
136 @classmethod
136 @classmethod
137 def get_instance(cls, name):
137 def get_instance(cls, name):
138 return cls.instances[name]
138 return cls.instances[name]
139
139
140
140
141 class KeyCompletable:
141 class KeyCompletable:
142 def __init__(self, things=()):
142 def __init__(self, things=()):
143 self.things = things
143 self.things = things
144
144
145 def _ipython_key_completions_(self):
145 def _ipython_key_completions_(self):
146 return list(self.things)
146 return list(self.things)
147
147
148
148
149 class TestCompleter(unittest.TestCase):
149 class TestCompleter(unittest.TestCase):
150 def setUp(self):
150 def setUp(self):
151 """
151 """
152 We want to silence all PendingDeprecationWarning when testing the completer
152 We want to silence all PendingDeprecationWarning when testing the completer
153 """
153 """
154 self._assertwarns = self.assertWarns(PendingDeprecationWarning)
154 self._assertwarns = self.assertWarns(PendingDeprecationWarning)
155 self._assertwarns.__enter__()
155 self._assertwarns.__enter__()
156
156
157 def tearDown(self):
157 def tearDown(self):
158 try:
158 try:
159 self._assertwarns.__exit__(None, None, None)
159 self._assertwarns.__exit__(None, None, None)
160 except AssertionError:
160 except AssertionError:
161 pass
161 pass
162
162
163 def test_custom_completion_error(self):
163 def test_custom_completion_error(self):
164 """Test that errors from custom attribute completers are silenced."""
164 """Test that errors from custom attribute completers are silenced."""
165 ip = get_ipython()
165 ip = get_ipython()
166
166
167 class A:
167 class A:
168 pass
168 pass
169
169
170 ip.user_ns["x"] = A()
170 ip.user_ns["x"] = A()
171
171
172 @complete_object.register(A)
172 @complete_object.register(A)
173 def complete_A(a, existing_completions):
173 def complete_A(a, existing_completions):
174 raise TypeError("this should be silenced")
174 raise TypeError("this should be silenced")
175
175
176 ip.complete("x.")
176 ip.complete("x.")
177
177
178 def test_custom_completion_ordering(self):
178 def test_custom_completion_ordering(self):
179 """Test that errors from custom attribute completers are silenced."""
179 """Test that errors from custom attribute completers are silenced."""
180 ip = get_ipython()
180 ip = get_ipython()
181
181
182 _, matches = ip.complete('in')
182 _, matches = ip.complete('in')
183 assert matches.index('input') < matches.index('int')
183 assert matches.index('input') < matches.index('int')
184
184
185 def complete_example(a):
185 def complete_example(a):
186 return ['example2', 'example1']
186 return ['example2', 'example1']
187
187
188 ip.Completer.custom_completers.add_re('ex*', complete_example)
188 ip.Completer.custom_completers.add_re('ex*', complete_example)
189 _, matches = ip.complete('ex')
189 _, matches = ip.complete('ex')
190 assert matches.index('example2') < matches.index('example1')
190 assert matches.index('example2') < matches.index('example1')
191
191
192 def test_unicode_completions(self):
192 def test_unicode_completions(self):
193 ip = get_ipython()
193 ip = get_ipython()
194 # Some strings that trigger different types of completion. Check them both
194 # Some strings that trigger different types of completion. Check them both
195 # in str and unicode forms
195 # in str and unicode forms
196 s = ["ru", "%ru", "cd /", "floa", "float(x)/"]
196 s = ["ru", "%ru", "cd /", "floa", "float(x)/"]
197 for t in s + list(map(str, s)):
197 for t in s + list(map(str, s)):
198 # We don't need to check exact completion values (they may change
198 # We don't need to check exact completion values (they may change
199 # depending on the state of the namespace, but at least no exceptions
199 # depending on the state of the namespace, but at least no exceptions
200 # should be thrown and the return value should be a pair of text, list
200 # should be thrown and the return value should be a pair of text, list
201 # values.
201 # values.
202 text, matches = ip.complete(t)
202 text, matches = ip.complete(t)
203 nt.assert_true(isinstance(text, str))
203 nt.assert_true(isinstance(text, str))
204 nt.assert_true(isinstance(matches, list))
204 nt.assert_true(isinstance(matches, list))
205
205
206 def test_latex_completions(self):
206 def test_latex_completions(self):
207 from IPython.core.latex_symbols import latex_symbols
207 from IPython.core.latex_symbols import latex_symbols
208 import random
208 import random
209
209
210 ip = get_ipython()
210 ip = get_ipython()
211 # Test some random unicode symbols
211 # Test some random unicode symbols
212 keys = random.sample(latex_symbols.keys(), 10)
212 keys = random.sample(latex_symbols.keys(), 10)
213 for k in keys:
213 for k in keys:
214 text, matches = ip.complete(k)
214 text, matches = ip.complete(k)
215 nt.assert_equal(len(matches), 1)
216 nt.assert_equal(text, k)
215 nt.assert_equal(text, k)
217 nt.assert_equal(matches[0], latex_symbols[k])
216 nt.assert_equal(matches, [latex_symbols[k]])
218 # Test a more complex line
217 # Test a more complex line
219 text, matches = ip.complete("print(\\alpha")
218 text, matches = ip.complete("print(\\alpha")
220 nt.assert_equal(text, "\\alpha")
219 nt.assert_equal(text, "\\alpha")
221 nt.assert_equal(matches[0], latex_symbols["\\alpha"])
220 nt.assert_equal(matches[0], latex_symbols["\\alpha"])
222 # Test multiple matching latex symbols
221 # Test multiple matching latex symbols
223 text, matches = ip.complete("\\al")
222 text, matches = ip.complete("\\al")
224 nt.assert_in("\\alpha", matches)
223 nt.assert_in("\\alpha", matches)
225 nt.assert_in("\\aleph", matches)
224 nt.assert_in("\\aleph", matches)
226
225
227 def test_latex_no_results(self):
226 def test_latex_no_results(self):
228 """
227 """
229 forward latex should really return nothing in either field if nothing is found.
228 forward latex should really return nothing in either field if nothing is found.
230 """
229 """
231 ip = get_ipython()
230 ip = get_ipython()
232 text, matches = ip.Completer.latex_matches("\\really_i_should_match_nothing")
231 text, matches = ip.Completer.latex_matches("\\really_i_should_match_nothing")
233 nt.assert_equal(text, "")
232 nt.assert_equal(text, "")
234 nt.assert_equal(matches, [])
233 nt.assert_equal(matches, [])
235
234
236 def test_back_latex_completion(self):
235 def test_back_latex_completion(self):
237 ip = get_ipython()
236 ip = get_ipython()
238
237
239 # do not return more than 1 matches fro \beta, only the latex one.
238 # do not return more than 1 matches fro \beta, only the latex one.
240 name, matches = ip.complete("\\Ξ²")
239 name, matches = ip.complete("\\Ξ²")
241 nt.assert_equal(matches, ['\\beta'])
240 nt.assert_equal(matches, ['\\beta'])
242
241
243 def test_back_unicode_completion(self):
242 def test_back_unicode_completion(self):
244 ip = get_ipython()
243 ip = get_ipython()
245
244
246 name, matches = ip.complete("\\β…€")
245 name, matches = ip.complete("\\β…€")
247 nt.assert_equal(matches, ["\\ROMAN NUMERAL FIVE"])
246 nt.assert_equal(matches, ["\\ROMAN NUMERAL FIVE"])
248
247
249 def test_forward_unicode_completion(self):
248 def test_forward_unicode_completion(self):
250 ip = get_ipython()
249 ip = get_ipython()
251
250
252 name, matches = ip.complete("\\ROMAN NUMERAL FIVE")
251 name, matches = ip.complete("\\ROMAN NUMERAL FIVE")
253 nt.assert_equal(len(matches), 1)
252 nt.assert_equal(matches, ["β…€"] ) # This is not a V
254 nt.assert_equal(matches[0], "β…€")
253 nt.assert_equal(matches, ["\u2164"] ) # same as above but explicit.
255
254
256 @nt.nottest # now we have a completion for \jmath
255 @nt.nottest # now we have a completion for \jmath
257 @decorators.knownfailureif(
256 @decorators.knownfailureif(
258 sys.platform == "win32", "Fails if there is a C:\\j... path"
257 sys.platform == "win32", "Fails if there is a C:\\j... path"
259 )
258 )
260 def test_no_ascii_back_completion(self):
259 def test_no_ascii_back_completion(self):
261 ip = get_ipython()
260 ip = get_ipython()
262 with TemporaryWorkingDirectory(): # Avoid any filename completions
261 with TemporaryWorkingDirectory(): # Avoid any filename completions
263 # single ascii letter that don't have yet completions
262 # single ascii letter that don't have yet completions
264 for letter in "jJ":
263 for letter in "jJ":
265 name, matches = ip.complete("\\" + letter)
264 name, matches = ip.complete("\\" + letter)
266 nt.assert_equal(matches, [])
265 nt.assert_equal(matches, [])
267
266
268 class CompletionSplitterTestCase(unittest.TestCase):
267 class CompletionSplitterTestCase(unittest.TestCase):
269 def setUp(self):
268 def setUp(self):
270 self.sp = completer.CompletionSplitter()
269 self.sp = completer.CompletionSplitter()
271
270
272 def test_delim_setting(self):
271 def test_delim_setting(self):
273 self.sp.delims = " "
272 self.sp.delims = " "
274 nt.assert_equal(self.sp.delims, " ")
273 nt.assert_equal(self.sp.delims, " ")
275 nt.assert_equal(self.sp._delim_expr, r"[\ ]")
274 nt.assert_equal(self.sp._delim_expr, r"[\ ]")
276
275
277 def test_spaces(self):
276 def test_spaces(self):
278 """Test with only spaces as split chars."""
277 """Test with only spaces as split chars."""
279 self.sp.delims = " "
278 self.sp.delims = " "
280 t = [("foo", "", "foo"), ("run foo", "", "foo"), ("run foo", "bar", "foo")]
279 t = [("foo", "", "foo"), ("run foo", "", "foo"), ("run foo", "bar", "foo")]
281 check_line_split(self.sp, t)
280 check_line_split(self.sp, t)
282
281
283 def test_has_open_quotes1(self):
282 def test_has_open_quotes1(self):
284 for s in ["'", "'''", "'hi' '"]:
283 for s in ["'", "'''", "'hi' '"]:
285 nt.assert_equal(completer.has_open_quotes(s), "'")
284 nt.assert_equal(completer.has_open_quotes(s), "'")
286
285
287 def test_has_open_quotes2(self):
286 def test_has_open_quotes2(self):
288 for s in ['"', '"""', '"hi" "']:
287 for s in ['"', '"""', '"hi" "']:
289 nt.assert_equal(completer.has_open_quotes(s), '"')
288 nt.assert_equal(completer.has_open_quotes(s), '"')
290
289
291 def test_has_open_quotes3(self):
290 def test_has_open_quotes3(self):
292 for s in ["''", "''' '''", "'hi' 'ipython'"]:
291 for s in ["''", "''' '''", "'hi' 'ipython'"]:
293 nt.assert_false(completer.has_open_quotes(s))
292 nt.assert_false(completer.has_open_quotes(s))
294
293
295 def test_has_open_quotes4(self):
294 def test_has_open_quotes4(self):
296 for s in ['""', '""" """', '"hi" "ipython"']:
295 for s in ['""', '""" """', '"hi" "ipython"']:
297 nt.assert_false(completer.has_open_quotes(s))
296 nt.assert_false(completer.has_open_quotes(s))
298
297
299 @decorators.knownfailureif(
298 @decorators.knownfailureif(
300 sys.platform == "win32", "abspath completions fail on Windows"
299 sys.platform == "win32", "abspath completions fail on Windows"
301 )
300 )
302 def test_abspath_file_completions(self):
301 def test_abspath_file_completions(self):
303 ip = get_ipython()
302 ip = get_ipython()
304 with TemporaryDirectory() as tmpdir:
303 with TemporaryDirectory() as tmpdir:
305 prefix = os.path.join(tmpdir, "foo")
304 prefix = os.path.join(tmpdir, "foo")
306 suffixes = ["1", "2"]
305 suffixes = ["1", "2"]
307 names = [prefix + s for s in suffixes]
306 names = [prefix + s for s in suffixes]
308 for n in names:
307 for n in names:
309 open(n, "w").close()
308 open(n, "w").close()
310
309
311 # Check simple completion
310 # Check simple completion
312 c = ip.complete(prefix)[1]
311 c = ip.complete(prefix)[1]
313 nt.assert_equal(c, names)
312 nt.assert_equal(c, names)
314
313
315 # Now check with a function call
314 # Now check with a function call
316 cmd = 'a = f("%s' % prefix
315 cmd = 'a = f("%s' % prefix
317 c = ip.complete(prefix, cmd)[1]
316 c = ip.complete(prefix, cmd)[1]
318 comp = [prefix + s for s in suffixes]
317 comp = [prefix + s for s in suffixes]
319 nt.assert_equal(c, comp)
318 nt.assert_equal(c, comp)
320
319
321 def test_local_file_completions(self):
320 def test_local_file_completions(self):
322 ip = get_ipython()
321 ip = get_ipython()
323 with TemporaryWorkingDirectory():
322 with TemporaryWorkingDirectory():
324 prefix = "./foo"
323 prefix = "./foo"
325 suffixes = ["1", "2"]
324 suffixes = ["1", "2"]
326 names = [prefix + s for s in suffixes]
325 names = [prefix + s for s in suffixes]
327 for n in names:
326 for n in names:
328 open(n, "w").close()
327 open(n, "w").close()
329
328
330 # Check simple completion
329 # Check simple completion
331 c = ip.complete(prefix)[1]
330 c = ip.complete(prefix)[1]
332 nt.assert_equal(c, names)
331 nt.assert_equal(c, names)
333
332
334 # Now check with a function call
333 # Now check with a function call
335 cmd = 'a = f("%s' % prefix
334 cmd = 'a = f("%s' % prefix
336 c = ip.complete(prefix, cmd)[1]
335 c = ip.complete(prefix, cmd)[1]
337 comp = {prefix + s for s in suffixes}
336 comp = {prefix + s for s in suffixes}
338 nt.assert_true(comp.issubset(set(c)))
337 nt.assert_true(comp.issubset(set(c)))
339
338
340 def test_quoted_file_completions(self):
339 def test_quoted_file_completions(self):
341 ip = get_ipython()
340 ip = get_ipython()
342 with TemporaryWorkingDirectory():
341 with TemporaryWorkingDirectory():
343 name = "foo'bar"
342 name = "foo'bar"
344 open(name, "w").close()
343 open(name, "w").close()
345
344
346 # Don't escape Windows
345 # Don't escape Windows
347 escaped = name if sys.platform == "win32" else "foo\\'bar"
346 escaped = name if sys.platform == "win32" else "foo\\'bar"
348
347
349 # Single quote matches embedded single quote
348 # Single quote matches embedded single quote
350 text = "open('foo"
349 text = "open('foo"
351 c = ip.Completer._complete(
350 c = ip.Completer._complete(
352 cursor_line=0, cursor_pos=len(text), full_text=text
351 cursor_line=0, cursor_pos=len(text), full_text=text
353 )[1]
352 )[1]
354 nt.assert_equal(c, [escaped])
353 nt.assert_equal(c, [escaped])
355
354
356 # Double quote requires no escape
355 # Double quote requires no escape
357 text = 'open("foo'
356 text = 'open("foo'
358 c = ip.Completer._complete(
357 c = ip.Completer._complete(
359 cursor_line=0, cursor_pos=len(text), full_text=text
358 cursor_line=0, cursor_pos=len(text), full_text=text
360 )[1]
359 )[1]
361 nt.assert_equal(c, [name])
360 nt.assert_equal(c, [name])
362
361
363 # No quote requires an escape
362 # No quote requires an escape
364 text = "%ls foo"
363 text = "%ls foo"
365 c = ip.Completer._complete(
364 c = ip.Completer._complete(
366 cursor_line=0, cursor_pos=len(text), full_text=text
365 cursor_line=0, cursor_pos=len(text), full_text=text
367 )[1]
366 )[1]
368 nt.assert_equal(c, [escaped])
367 nt.assert_equal(c, [escaped])
369
368
370 def test_all_completions_dups(self):
369 def test_all_completions_dups(self):
371 """
370 """
372 Make sure the output of `IPCompleter.all_completions` does not have
371 Make sure the output of `IPCompleter.all_completions` does not have
373 duplicated prefixes.
372 duplicated prefixes.
374 """
373 """
375 ip = get_ipython()
374 ip = get_ipython()
376 c = ip.Completer
375 c = ip.Completer
377 ip.ex("class TestClass():\n\ta=1\n\ta1=2")
376 ip.ex("class TestClass():\n\ta=1\n\ta1=2")
378 for jedi_status in [True, False]:
377 for jedi_status in [True, False]:
379 with provisionalcompleter():
378 with provisionalcompleter():
380 ip.Completer.use_jedi = jedi_status
379 ip.Completer.use_jedi = jedi_status
381 matches = c.all_completions("TestCl")
380 matches = c.all_completions("TestCl")
382 assert matches == ['TestClass'], jedi_status
381 assert matches == ['TestClass'], jedi_status
383 matches = c.all_completions("TestClass.")
382 matches = c.all_completions("TestClass.")
384 assert len(matches) > 2, jedi_status
383 assert len(matches) > 2, jedi_status
385 matches = c.all_completions("TestClass.a")
384 matches = c.all_completions("TestClass.a")
386 assert matches == ['TestClass.a', 'TestClass.a1'], jedi_status
385 assert matches == ['TestClass.a', 'TestClass.a1'], jedi_status
387
386
388 def test_jedi(self):
387 def test_jedi(self):
389 """
388 """
390 A couple of issue we had with Jedi
389 A couple of issue we had with Jedi
391 """
390 """
392 ip = get_ipython()
391 ip = get_ipython()
393
392
394 def _test_complete(reason, s, comp, start=None, end=None):
393 def _test_complete(reason, s, comp, start=None, end=None):
395 l = len(s)
394 l = len(s)
396 start = start if start is not None else l
395 start = start if start is not None else l
397 end = end if end is not None else l
396 end = end if end is not None else l
398 with provisionalcompleter():
397 with provisionalcompleter():
399 ip.Completer.use_jedi = True
398 ip.Completer.use_jedi = True
400 completions = set(ip.Completer.completions(s, l))
399 completions = set(ip.Completer.completions(s, l))
401 ip.Completer.use_jedi = False
400 ip.Completer.use_jedi = False
402 assert_in(Completion(start, end, comp), completions, reason)
401 assert_in(Completion(start, end, comp), completions, reason)
403
402
404 def _test_not_complete(reason, s, comp):
403 def _test_not_complete(reason, s, comp):
405 l = len(s)
404 l = len(s)
406 with provisionalcompleter():
405 with provisionalcompleter():
407 ip.Completer.use_jedi = True
406 ip.Completer.use_jedi = True
408 completions = set(ip.Completer.completions(s, l))
407 completions = set(ip.Completer.completions(s, l))
409 ip.Completer.use_jedi = False
408 ip.Completer.use_jedi = False
410 assert_not_in(Completion(l, l, comp), completions, reason)
409 assert_not_in(Completion(l, l, comp), completions, reason)
411
410
412 import jedi
411 import jedi
413
412
414 jedi_version = tuple(int(i) for i in jedi.__version__.split(".")[:3])
413 jedi_version = tuple(int(i) for i in jedi.__version__.split(".")[:3])
415 if jedi_version > (0, 10):
414 if jedi_version > (0, 10):
416 yield _test_complete, "jedi >0.9 should complete and not crash", "a=1;a.", "real"
415 yield _test_complete, "jedi >0.9 should complete and not crash", "a=1;a.", "real"
417 yield _test_complete, "can infer first argument", 'a=(1,"foo");a[0].', "real"
416 yield _test_complete, "can infer first argument", 'a=(1,"foo");a[0].', "real"
418 yield _test_complete, "can infer second argument", 'a=(1,"foo");a[1].', "capitalize"
417 yield _test_complete, "can infer second argument", 'a=(1,"foo");a[1].', "capitalize"
419 yield _test_complete, "cover duplicate completions", "im", "import", 0, 2
418 yield _test_complete, "cover duplicate completions", "im", "import", 0, 2
420
419
421 yield _test_not_complete, "does not mix types", 'a=(1,"foo");a[0].', "capitalize"
420 yield _test_not_complete, "does not mix types", 'a=(1,"foo");a[0].', "capitalize"
422
421
423 def test_completion_have_signature(self):
422 def test_completion_have_signature(self):
424 """
423 """
425 Lets make sure jedi is capable of pulling out the signature of the function we are completing.
424 Lets make sure jedi is capable of pulling out the signature of the function we are completing.
426 """
425 """
427 ip = get_ipython()
426 ip = get_ipython()
428 with provisionalcompleter():
427 with provisionalcompleter():
429 ip.Completer.use_jedi = True
428 ip.Completer.use_jedi = True
430 completions = ip.Completer.completions("ope", 3)
429 completions = ip.Completer.completions("ope", 3)
431 c = next(completions) # should be `open`
430 c = next(completions) # should be `open`
432 ip.Completer.use_jedi = False
431 ip.Completer.use_jedi = False
433 assert "file" in c.signature, "Signature of function was not found by completer"
432 assert "file" in c.signature, "Signature of function was not found by completer"
434 assert (
433 assert (
435 "encoding" in c.signature
434 "encoding" in c.signature
436 ), "Signature of function was not found by completer"
435 ), "Signature of function was not found by completer"
437
436
438 def test_deduplicate_completions(self):
437 def test_deduplicate_completions(self):
439 """
438 """
440 Test that completions are correctly deduplicated (even if ranges are not the same)
439 Test that completions are correctly deduplicated (even if ranges are not the same)
441 """
440 """
442 ip = get_ipython()
441 ip = get_ipython()
443 ip.ex(
442 ip.ex(
444 textwrap.dedent(
443 textwrap.dedent(
445 """
444 """
446 class Z:
445 class Z:
447 zoo = 1
446 zoo = 1
448 """
447 """
449 )
448 )
450 )
449 )
451 with provisionalcompleter():
450 with provisionalcompleter():
452 ip.Completer.use_jedi = True
451 ip.Completer.use_jedi = True
453 l = list(
452 l = list(
454 _deduplicate_completions("Z.z", ip.Completer.completions("Z.z", 3))
453 _deduplicate_completions("Z.z", ip.Completer.completions("Z.z", 3))
455 )
454 )
456 ip.Completer.use_jedi = False
455 ip.Completer.use_jedi = False
457
456
458 assert len(l) == 1, "Completions (Z.z<tab>) correctly deduplicate: %s " % l
457 assert len(l) == 1, "Completions (Z.z<tab>) correctly deduplicate: %s " % l
459 assert l[0].text == "zoo" # and not `it.accumulate`
458 assert l[0].text == "zoo" # and not `it.accumulate`
460
459
461 def test_greedy_completions(self):
460 def test_greedy_completions(self):
462 """
461 """
463 Test the capability of the Greedy completer.
462 Test the capability of the Greedy completer.
464
463
465 Most of the test here does not really show off the greedy completer, for proof
464 Most of the test here does not really show off the greedy completer, for proof
466 each of the text below now pass with Jedi. The greedy completer is capable of more.
465 each of the text below now pass with Jedi. The greedy completer is capable of more.
467
466
468 See the :any:`test_dict_key_completion_contexts`
467 See the :any:`test_dict_key_completion_contexts`
469
468
470 """
469 """
471 ip = get_ipython()
470 ip = get_ipython()
472 ip.ex("a=list(range(5))")
471 ip.ex("a=list(range(5))")
473 _, c = ip.complete(".", line="a[0].")
472 _, c = ip.complete(".", line="a[0].")
474 nt.assert_false(".real" in c, "Shouldn't have completed on a[0]: %s" % c)
473 nt.assert_false(".real" in c, "Shouldn't have completed on a[0]: %s" % c)
475
474
476 def _(line, cursor_pos, expect, message, completion):
475 def _(line, cursor_pos, expect, message, completion):
477 with greedy_completion(), provisionalcompleter():
476 with greedy_completion(), provisionalcompleter():
478 ip.Completer.use_jedi = False
477 ip.Completer.use_jedi = False
479 _, c = ip.complete(".", line=line, cursor_pos=cursor_pos)
478 _, c = ip.complete(".", line=line, cursor_pos=cursor_pos)
480 nt.assert_in(expect, c, message % c)
479 nt.assert_in(expect, c, message % c)
481
480
482 ip.Completer.use_jedi = True
481 ip.Completer.use_jedi = True
483 with provisionalcompleter():
482 with provisionalcompleter():
484 completions = ip.Completer.completions(line, cursor_pos)
483 completions = ip.Completer.completions(line, cursor_pos)
485 nt.assert_in(completion, completions)
484 nt.assert_in(completion, completions)
486
485
487 with provisionalcompleter():
486 with provisionalcompleter():
488 yield _, "a[0].", 5, "a[0].real", "Should have completed on a[0].: %s", Completion(
487 yield _, "a[0].", 5, "a[0].real", "Should have completed on a[0].: %s", Completion(
489 5, 5, "real"
488 5, 5, "real"
490 )
489 )
491 yield _, "a[0].r", 6, "a[0].real", "Should have completed on a[0].r: %s", Completion(
490 yield _, "a[0].r", 6, "a[0].real", "Should have completed on a[0].r: %s", Completion(
492 5, 6, "real"
491 5, 6, "real"
493 )
492 )
494
493
495 yield _, "a[0].from_", 10, "a[0].from_bytes", "Should have completed on a[0].from_: %s", Completion(
494 yield _, "a[0].from_", 10, "a[0].from_bytes", "Should have completed on a[0].from_: %s", Completion(
496 5, 10, "from_bytes"
495 5, 10, "from_bytes"
497 )
496 )
498
497
499 def test_omit__names(self):
498 def test_omit__names(self):
500 # also happens to test IPCompleter as a configurable
499 # also happens to test IPCompleter as a configurable
501 ip = get_ipython()
500 ip = get_ipython()
502 ip._hidden_attr = 1
501 ip._hidden_attr = 1
503 ip._x = {}
502 ip._x = {}
504 c = ip.Completer
503 c = ip.Completer
505 ip.ex("ip=get_ipython()")
504 ip.ex("ip=get_ipython()")
506 cfg = Config()
505 cfg = Config()
507 cfg.IPCompleter.omit__names = 0
506 cfg.IPCompleter.omit__names = 0
508 c.update_config(cfg)
507 c.update_config(cfg)
509 with provisionalcompleter():
508 with provisionalcompleter():
510 c.use_jedi = False
509 c.use_jedi = False
511 s, matches = c.complete("ip.")
510 s, matches = c.complete("ip.")
512 nt.assert_in("ip.__str__", matches)
511 nt.assert_in("ip.__str__", matches)
513 nt.assert_in("ip._hidden_attr", matches)
512 nt.assert_in("ip._hidden_attr", matches)
514
513
515 # c.use_jedi = True
514 # c.use_jedi = True
516 # completions = set(c.completions('ip.', 3))
515 # completions = set(c.completions('ip.', 3))
517 # nt.assert_in(Completion(3, 3, '__str__'), completions)
516 # nt.assert_in(Completion(3, 3, '__str__'), completions)
518 # nt.assert_in(Completion(3,3, "_hidden_attr"), completions)
517 # nt.assert_in(Completion(3,3, "_hidden_attr"), completions)
519
518
520 cfg = Config()
519 cfg = Config()
521 cfg.IPCompleter.omit__names = 1
520 cfg.IPCompleter.omit__names = 1
522 c.update_config(cfg)
521 c.update_config(cfg)
523 with provisionalcompleter():
522 with provisionalcompleter():
524 c.use_jedi = False
523 c.use_jedi = False
525 s, matches = c.complete("ip.")
524 s, matches = c.complete("ip.")
526 nt.assert_not_in("ip.__str__", matches)
525 nt.assert_not_in("ip.__str__", matches)
527 # nt.assert_in('ip._hidden_attr', matches)
526 # nt.assert_in('ip._hidden_attr', matches)
528
527
529 # c.use_jedi = True
528 # c.use_jedi = True
530 # completions = set(c.completions('ip.', 3))
529 # completions = set(c.completions('ip.', 3))
531 # nt.assert_not_in(Completion(3,3,'__str__'), completions)
530 # nt.assert_not_in(Completion(3,3,'__str__'), completions)
532 # nt.assert_in(Completion(3,3, "_hidden_attr"), completions)
531 # nt.assert_in(Completion(3,3, "_hidden_attr"), completions)
533
532
534 cfg = Config()
533 cfg = Config()
535 cfg.IPCompleter.omit__names = 2
534 cfg.IPCompleter.omit__names = 2
536 c.update_config(cfg)
535 c.update_config(cfg)
537 with provisionalcompleter():
536 with provisionalcompleter():
538 c.use_jedi = False
537 c.use_jedi = False
539 s, matches = c.complete("ip.")
538 s, matches = c.complete("ip.")
540 nt.assert_not_in("ip.__str__", matches)
539 nt.assert_not_in("ip.__str__", matches)
541 nt.assert_not_in("ip._hidden_attr", matches)
540 nt.assert_not_in("ip._hidden_attr", matches)
542
541
543 # c.use_jedi = True
542 # c.use_jedi = True
544 # completions = set(c.completions('ip.', 3))
543 # completions = set(c.completions('ip.', 3))
545 # nt.assert_not_in(Completion(3,3,'__str__'), completions)
544 # nt.assert_not_in(Completion(3,3,'__str__'), completions)
546 # nt.assert_not_in(Completion(3,3, "_hidden_attr"), completions)
545 # nt.assert_not_in(Completion(3,3, "_hidden_attr"), completions)
547
546
548 with provisionalcompleter():
547 with provisionalcompleter():
549 c.use_jedi = False
548 c.use_jedi = False
550 s, matches = c.complete("ip._x.")
549 s, matches = c.complete("ip._x.")
551 nt.assert_in("ip._x.keys", matches)
550 nt.assert_in("ip._x.keys", matches)
552
551
553 # c.use_jedi = True
552 # c.use_jedi = True
554 # completions = set(c.completions('ip._x.', 6))
553 # completions = set(c.completions('ip._x.', 6))
555 # nt.assert_in(Completion(6,6, "keys"), completions)
554 # nt.assert_in(Completion(6,6, "keys"), completions)
556
555
557 del ip._hidden_attr
556 del ip._hidden_attr
558 del ip._x
557 del ip._x
559
558
560 def test_limit_to__all__False_ok(self):
559 def test_limit_to__all__False_ok(self):
561 """
560 """
562 Limit to all is deprecated, once we remove it this test can go away.
561 Limit to all is deprecated, once we remove it this test can go away.
563 """
562 """
564 ip = get_ipython()
563 ip = get_ipython()
565 c = ip.Completer
564 c = ip.Completer
566 c.use_jedi = False
565 c.use_jedi = False
567 ip.ex("class D: x=24")
566 ip.ex("class D: x=24")
568 ip.ex("d=D()")
567 ip.ex("d=D()")
569 cfg = Config()
568 cfg = Config()
570 cfg.IPCompleter.limit_to__all__ = False
569 cfg.IPCompleter.limit_to__all__ = False
571 c.update_config(cfg)
570 c.update_config(cfg)
572 s, matches = c.complete("d.")
571 s, matches = c.complete("d.")
573 nt.assert_in("d.x", matches)
572 nt.assert_in("d.x", matches)
574
573
575 def test_get__all__entries_ok(self):
574 def test_get__all__entries_ok(self):
576 class A:
575 class A:
577 __all__ = ["x", 1]
576 __all__ = ["x", 1]
578
577
579 words = completer.get__all__entries(A())
578 words = completer.get__all__entries(A())
580 nt.assert_equal(words, ["x"])
579 nt.assert_equal(words, ["x"])
581
580
582 def test_get__all__entries_no__all__ok(self):
581 def test_get__all__entries_no__all__ok(self):
583 class A:
582 class A:
584 pass
583 pass
585
584
586 words = completer.get__all__entries(A())
585 words = completer.get__all__entries(A())
587 nt.assert_equal(words, [])
586 nt.assert_equal(words, [])
588
587
589 def test_func_kw_completions(self):
588 def test_func_kw_completions(self):
590 ip = get_ipython()
589 ip = get_ipython()
591 c = ip.Completer
590 c = ip.Completer
592 c.use_jedi = False
591 c.use_jedi = False
593 ip.ex("def myfunc(a=1,b=2): return a+b")
592 ip.ex("def myfunc(a=1,b=2): return a+b")
594 s, matches = c.complete(None, "myfunc(1,b")
593 s, matches = c.complete(None, "myfunc(1,b")
595 nt.assert_in("b=", matches)
594 nt.assert_in("b=", matches)
596 # Simulate completing with cursor right after b (pos==10):
595 # Simulate completing with cursor right after b (pos==10):
597 s, matches = c.complete(None, "myfunc(1,b)", 10)
596 s, matches = c.complete(None, "myfunc(1,b)", 10)
598 nt.assert_in("b=", matches)
597 nt.assert_in("b=", matches)
599 s, matches = c.complete(None, 'myfunc(a="escaped\\")string",b')
598 s, matches = c.complete(None, 'myfunc(a="escaped\\")string",b')
600 nt.assert_in("b=", matches)
599 nt.assert_in("b=", matches)
601 # builtin function
600 # builtin function
602 s, matches = c.complete(None, "min(k, k")
601 s, matches = c.complete(None, "min(k, k")
603 nt.assert_in("key=", matches)
602 nt.assert_in("key=", matches)
604
603
605 def test_default_arguments_from_docstring(self):
604 def test_default_arguments_from_docstring(self):
606 ip = get_ipython()
605 ip = get_ipython()
607 c = ip.Completer
606 c = ip.Completer
608 kwd = c._default_arguments_from_docstring("min(iterable[, key=func]) -> value")
607 kwd = c._default_arguments_from_docstring("min(iterable[, key=func]) -> value")
609 nt.assert_equal(kwd, ["key"])
608 nt.assert_equal(kwd, ["key"])
610 # with cython type etc
609 # with cython type etc
611 kwd = c._default_arguments_from_docstring(
610 kwd = c._default_arguments_from_docstring(
612 "Minuit.migrad(self, int ncall=10000, resume=True, int nsplit=1)\n"
611 "Minuit.migrad(self, int ncall=10000, resume=True, int nsplit=1)\n"
613 )
612 )
614 nt.assert_equal(kwd, ["ncall", "resume", "nsplit"])
613 nt.assert_equal(kwd, ["ncall", "resume", "nsplit"])
615 # white spaces
614 # white spaces
616 kwd = c._default_arguments_from_docstring(
615 kwd = c._default_arguments_from_docstring(
617 "\n Minuit.migrad(self, int ncall=10000, resume=True, int nsplit=1)\n"
616 "\n Minuit.migrad(self, int ncall=10000, resume=True, int nsplit=1)\n"
618 )
617 )
619 nt.assert_equal(kwd, ["ncall", "resume", "nsplit"])
618 nt.assert_equal(kwd, ["ncall", "resume", "nsplit"])
620
619
621 def test_line_magics(self):
620 def test_line_magics(self):
622 ip = get_ipython()
621 ip = get_ipython()
623 c = ip.Completer
622 c = ip.Completer
624 s, matches = c.complete(None, "lsmag")
623 s, matches = c.complete(None, "lsmag")
625 nt.assert_in("%lsmagic", matches)
624 nt.assert_in("%lsmagic", matches)
626 s, matches = c.complete(None, "%lsmag")
625 s, matches = c.complete(None, "%lsmag")
627 nt.assert_in("%lsmagic", matches)
626 nt.assert_in("%lsmagic", matches)
628
627
629 def test_cell_magics(self):
628 def test_cell_magics(self):
630 from IPython.core.magic import register_cell_magic
629 from IPython.core.magic import register_cell_magic
631
630
632 @register_cell_magic
631 @register_cell_magic
633 def _foo_cellm(line, cell):
632 def _foo_cellm(line, cell):
634 pass
633 pass
635
634
636 ip = get_ipython()
635 ip = get_ipython()
637 c = ip.Completer
636 c = ip.Completer
638
637
639 s, matches = c.complete(None, "_foo_ce")
638 s, matches = c.complete(None, "_foo_ce")
640 nt.assert_in("%%_foo_cellm", matches)
639 nt.assert_in("%%_foo_cellm", matches)
641 s, matches = c.complete(None, "%%_foo_ce")
640 s, matches = c.complete(None, "%%_foo_ce")
642 nt.assert_in("%%_foo_cellm", matches)
641 nt.assert_in("%%_foo_cellm", matches)
643
642
644 def test_line_cell_magics(self):
643 def test_line_cell_magics(self):
645 from IPython.core.magic import register_line_cell_magic
644 from IPython.core.magic import register_line_cell_magic
646
645
647 @register_line_cell_magic
646 @register_line_cell_magic
648 def _bar_cellm(line, cell):
647 def _bar_cellm(line, cell):
649 pass
648 pass
650
649
651 ip = get_ipython()
650 ip = get_ipython()
652 c = ip.Completer
651 c = ip.Completer
653
652
654 # The policy here is trickier, see comments in completion code. The
653 # The policy here is trickier, see comments in completion code. The
655 # returned values depend on whether the user passes %% or not explicitly,
654 # returned values depend on whether the user passes %% or not explicitly,
656 # and this will show a difference if the same name is both a line and cell
655 # and this will show a difference if the same name is both a line and cell
657 # magic.
656 # magic.
658 s, matches = c.complete(None, "_bar_ce")
657 s, matches = c.complete(None, "_bar_ce")
659 nt.assert_in("%_bar_cellm", matches)
658 nt.assert_in("%_bar_cellm", matches)
660 nt.assert_in("%%_bar_cellm", matches)
659 nt.assert_in("%%_bar_cellm", matches)
661 s, matches = c.complete(None, "%_bar_ce")
660 s, matches = c.complete(None, "%_bar_ce")
662 nt.assert_in("%_bar_cellm", matches)
661 nt.assert_in("%_bar_cellm", matches)
663 nt.assert_in("%%_bar_cellm", matches)
662 nt.assert_in("%%_bar_cellm", matches)
664 s, matches = c.complete(None, "%%_bar_ce")
663 s, matches = c.complete(None, "%%_bar_ce")
665 nt.assert_not_in("%_bar_cellm", matches)
664 nt.assert_not_in("%_bar_cellm", matches)
666 nt.assert_in("%%_bar_cellm", matches)
665 nt.assert_in("%%_bar_cellm", matches)
667
666
668 def test_magic_completion_order(self):
667 def test_magic_completion_order(self):
669 ip = get_ipython()
668 ip = get_ipython()
670 c = ip.Completer
669 c = ip.Completer
671
670
672 # Test ordering of line and cell magics.
671 # Test ordering of line and cell magics.
673 text, matches = c.complete("timeit")
672 text, matches = c.complete("timeit")
674 nt.assert_equal(matches, ["%timeit", "%%timeit"])
673 nt.assert_equal(matches, ["%timeit", "%%timeit"])
675
674
676 def test_magic_completion_shadowing(self):
675 def test_magic_completion_shadowing(self):
677 ip = get_ipython()
676 ip = get_ipython()
678 c = ip.Completer
677 c = ip.Completer
679 c.use_jedi = False
678 c.use_jedi = False
680
679
681 # Before importing matplotlib, %matplotlib magic should be the only option.
680 # Before importing matplotlib, %matplotlib magic should be the only option.
682 text, matches = c.complete("mat")
681 text, matches = c.complete("mat")
683 nt.assert_equal(matches, ["%matplotlib"])
682 nt.assert_equal(matches, ["%matplotlib"])
684
683
685 # The newly introduced name should shadow the magic.
684 # The newly introduced name should shadow the magic.
686 ip.run_cell("matplotlib = 1")
685 ip.run_cell("matplotlib = 1")
687 text, matches = c.complete("mat")
686 text, matches = c.complete("mat")
688 nt.assert_equal(matches, ["matplotlib"])
687 nt.assert_equal(matches, ["matplotlib"])
689
688
690 # After removing matplotlib from namespace, the magic should again be
689 # After removing matplotlib from namespace, the magic should again be
691 # the only option.
690 # the only option.
692 del ip.user_ns["matplotlib"]
691 del ip.user_ns["matplotlib"]
693 text, matches = c.complete("mat")
692 text, matches = c.complete("mat")
694 nt.assert_equal(matches, ["%matplotlib"])
693 nt.assert_equal(matches, ["%matplotlib"])
695
694
696 def test_magic_completion_shadowing_explicit(self):
695 def test_magic_completion_shadowing_explicit(self):
697 """
696 """
698 If the user try to complete a shadowed magic, and explicit % start should
697 If the user try to complete a shadowed magic, and explicit % start should
699 still return the completions.
698 still return the completions.
700 """
699 """
701 ip = get_ipython()
700 ip = get_ipython()
702 c = ip.Completer
701 c = ip.Completer
703
702
704 # Before importing matplotlib, %matplotlib magic should be the only option.
703 # Before importing matplotlib, %matplotlib magic should be the only option.
705 text, matches = c.complete("%mat")
704 text, matches = c.complete("%mat")
706 nt.assert_equal(matches, ["%matplotlib"])
705 nt.assert_equal(matches, ["%matplotlib"])
707
706
708 ip.run_cell("matplotlib = 1")
707 ip.run_cell("matplotlib = 1")
709
708
710 # After removing matplotlib from namespace, the magic should still be
709 # After removing matplotlib from namespace, the magic should still be
711 # the only option.
710 # the only option.
712 text, matches = c.complete("%mat")
711 text, matches = c.complete("%mat")
713 nt.assert_equal(matches, ["%matplotlib"])
712 nt.assert_equal(matches, ["%matplotlib"])
714
713
715 def test_magic_config(self):
714 def test_magic_config(self):
716 ip = get_ipython()
715 ip = get_ipython()
717 c = ip.Completer
716 c = ip.Completer
718
717
719 s, matches = c.complete(None, "conf")
718 s, matches = c.complete(None, "conf")
720 nt.assert_in("%config", matches)
719 nt.assert_in("%config", matches)
721 s, matches = c.complete(None, "conf")
720 s, matches = c.complete(None, "conf")
722 nt.assert_not_in("AliasManager", matches)
721 nt.assert_not_in("AliasManager", matches)
723 s, matches = c.complete(None, "config ")
722 s, matches = c.complete(None, "config ")
724 nt.assert_in("AliasManager", matches)
723 nt.assert_in("AliasManager", matches)
725 s, matches = c.complete(None, "%config ")
724 s, matches = c.complete(None, "%config ")
726 nt.assert_in("AliasManager", matches)
725 nt.assert_in("AliasManager", matches)
727 s, matches = c.complete(None, "config Ali")
726 s, matches = c.complete(None, "config Ali")
728 nt.assert_list_equal(["AliasManager"], matches)
727 nt.assert_list_equal(["AliasManager"], matches)
729 s, matches = c.complete(None, "%config Ali")
728 s, matches = c.complete(None, "%config Ali")
730 nt.assert_list_equal(["AliasManager"], matches)
729 nt.assert_list_equal(["AliasManager"], matches)
731 s, matches = c.complete(None, "config AliasManager")
730 s, matches = c.complete(None, "config AliasManager")
732 nt.assert_list_equal(["AliasManager"], matches)
731 nt.assert_list_equal(["AliasManager"], matches)
733 s, matches = c.complete(None, "%config AliasManager")
732 s, matches = c.complete(None, "%config AliasManager")
734 nt.assert_list_equal(["AliasManager"], matches)
733 nt.assert_list_equal(["AliasManager"], matches)
735 s, matches = c.complete(None, "config AliasManager.")
734 s, matches = c.complete(None, "config AliasManager.")
736 nt.assert_in("AliasManager.default_aliases", matches)
735 nt.assert_in("AliasManager.default_aliases", matches)
737 s, matches = c.complete(None, "%config AliasManager.")
736 s, matches = c.complete(None, "%config AliasManager.")
738 nt.assert_in("AliasManager.default_aliases", matches)
737 nt.assert_in("AliasManager.default_aliases", matches)
739 s, matches = c.complete(None, "config AliasManager.de")
738 s, matches = c.complete(None, "config AliasManager.de")
740 nt.assert_list_equal(["AliasManager.default_aliases"], matches)
739 nt.assert_list_equal(["AliasManager.default_aliases"], matches)
741 s, matches = c.complete(None, "config AliasManager.de")
740 s, matches = c.complete(None, "config AliasManager.de")
742 nt.assert_list_equal(["AliasManager.default_aliases"], matches)
741 nt.assert_list_equal(["AliasManager.default_aliases"], matches)
743
742
744 def test_magic_color(self):
743 def test_magic_color(self):
745 ip = get_ipython()
744 ip = get_ipython()
746 c = ip.Completer
745 c = ip.Completer
747
746
748 s, matches = c.complete(None, "colo")
747 s, matches = c.complete(None, "colo")
749 nt.assert_in("%colors", matches)
748 nt.assert_in("%colors", matches)
750 s, matches = c.complete(None, "colo")
749 s, matches = c.complete(None, "colo")
751 nt.assert_not_in("NoColor", matches)
750 nt.assert_not_in("NoColor", matches)
752 s, matches = c.complete(None, "%colors") # No trailing space
751 s, matches = c.complete(None, "%colors") # No trailing space
753 nt.assert_not_in("NoColor", matches)
752 nt.assert_not_in("NoColor", matches)
754 s, matches = c.complete(None, "colors ")
753 s, matches = c.complete(None, "colors ")
755 nt.assert_in("NoColor", matches)
754 nt.assert_in("NoColor", matches)
756 s, matches = c.complete(None, "%colors ")
755 s, matches = c.complete(None, "%colors ")
757 nt.assert_in("NoColor", matches)
756 nt.assert_in("NoColor", matches)
758 s, matches = c.complete(None, "colors NoCo")
757 s, matches = c.complete(None, "colors NoCo")
759 nt.assert_list_equal(["NoColor"], matches)
758 nt.assert_list_equal(["NoColor"], matches)
760 s, matches = c.complete(None, "%colors NoCo")
759 s, matches = c.complete(None, "%colors NoCo")
761 nt.assert_list_equal(["NoColor"], matches)
760 nt.assert_list_equal(["NoColor"], matches)
762
761
763 def test_match_dict_keys(self):
762 def test_match_dict_keys(self):
764 """
763 """
765 Test that match_dict_keys works on a couple of use case does return what
764 Test that match_dict_keys works on a couple of use case does return what
766 expected, and does not crash
765 expected, and does not crash
767 """
766 """
768 delims = " \t\n`!@#$^&*()=+[{]}\\|;:'\",<>?"
767 delims = " \t\n`!@#$^&*()=+[{]}\\|;:'\",<>?"
769
768
770 keys = ["foo", b"far"]
769 keys = ["foo", b"far"]
771 assert match_dict_keys(keys, "b'", delims=delims) == ("'", 2, ["far"])
770 assert match_dict_keys(keys, "b'", delims=delims) == ("'", 2, ["far"])
772 assert match_dict_keys(keys, "b'f", delims=delims) == ("'", 2, ["far"])
771 assert match_dict_keys(keys, "b'f", delims=delims) == ("'", 2, ["far"])
773 assert match_dict_keys(keys, 'b"', delims=delims) == ('"', 2, ["far"])
772 assert match_dict_keys(keys, 'b"', delims=delims) == ('"', 2, ["far"])
774 assert match_dict_keys(keys, 'b"f', delims=delims) == ('"', 2, ["far"])
773 assert match_dict_keys(keys, 'b"f', delims=delims) == ('"', 2, ["far"])
775
774
776 assert match_dict_keys(keys, "'", delims=delims) == ("'", 1, ["foo"])
775 assert match_dict_keys(keys, "'", delims=delims) == ("'", 1, ["foo"])
777 assert match_dict_keys(keys, "'f", delims=delims) == ("'", 1, ["foo"])
776 assert match_dict_keys(keys, "'f", delims=delims) == ("'", 1, ["foo"])
778 assert match_dict_keys(keys, '"', delims=delims) == ('"', 1, ["foo"])
777 assert match_dict_keys(keys, '"', delims=delims) == ('"', 1, ["foo"])
779 assert match_dict_keys(keys, '"f', delims=delims) == ('"', 1, ["foo"])
778 assert match_dict_keys(keys, '"f', delims=delims) == ('"', 1, ["foo"])
780
779
781 match_dict_keys
780 match_dict_keys
782
781
783 def test_dict_key_completion_string(self):
782 def test_dict_key_completion_string(self):
784 """Test dictionary key completion for string keys"""
783 """Test dictionary key completion for string keys"""
785 ip = get_ipython()
784 ip = get_ipython()
786 complete = ip.Completer.complete
785 complete = ip.Completer.complete
787
786
788 ip.user_ns["d"] = {"abc": None}
787 ip.user_ns["d"] = {"abc": None}
789
788
790 # check completion at different stages
789 # check completion at different stages
791 _, matches = complete(line_buffer="d[")
790 _, matches = complete(line_buffer="d[")
792 nt.assert_in("'abc'", matches)
791 nt.assert_in("'abc'", matches)
793 nt.assert_not_in("'abc']", matches)
792 nt.assert_not_in("'abc']", matches)
794
793
795 _, matches = complete(line_buffer="d['")
794 _, matches = complete(line_buffer="d['")
796 nt.assert_in("abc", matches)
795 nt.assert_in("abc", matches)
797 nt.assert_not_in("abc']", matches)
796 nt.assert_not_in("abc']", matches)
798
797
799 _, matches = complete(line_buffer="d['a")
798 _, matches = complete(line_buffer="d['a")
800 nt.assert_in("abc", matches)
799 nt.assert_in("abc", matches)
801 nt.assert_not_in("abc']", matches)
800 nt.assert_not_in("abc']", matches)
802
801
803 # check use of different quoting
802 # check use of different quoting
804 _, matches = complete(line_buffer='d["')
803 _, matches = complete(line_buffer='d["')
805 nt.assert_in("abc", matches)
804 nt.assert_in("abc", matches)
806 nt.assert_not_in('abc"]', matches)
805 nt.assert_not_in('abc"]', matches)
807
806
808 _, matches = complete(line_buffer='d["a')
807 _, matches = complete(line_buffer='d["a')
809 nt.assert_in("abc", matches)
808 nt.assert_in("abc", matches)
810 nt.assert_not_in('abc"]', matches)
809 nt.assert_not_in('abc"]', matches)
811
810
812 # check sensitivity to following context
811 # check sensitivity to following context
813 _, matches = complete(line_buffer="d[]", cursor_pos=2)
812 _, matches = complete(line_buffer="d[]", cursor_pos=2)
814 nt.assert_in("'abc'", matches)
813 nt.assert_in("'abc'", matches)
815
814
816 _, matches = complete(line_buffer="d['']", cursor_pos=3)
815 _, matches = complete(line_buffer="d['']", cursor_pos=3)
817 nt.assert_in("abc", matches)
816 nt.assert_in("abc", matches)
818 nt.assert_not_in("abc'", matches)
817 nt.assert_not_in("abc'", matches)
819 nt.assert_not_in("abc']", matches)
818 nt.assert_not_in("abc']", matches)
820
819
821 # check multiple solutions are correctly returned and that noise is not
820 # check multiple solutions are correctly returned and that noise is not
822 ip.user_ns["d"] = {
821 ip.user_ns["d"] = {
823 "abc": None,
822 "abc": None,
824 "abd": None,
823 "abd": None,
825 "bad": None,
824 "bad": None,
826 object(): None,
825 object(): None,
827 5: None,
826 5: None,
828 }
827 }
829
828
830 _, matches = complete(line_buffer="d['a")
829 _, matches = complete(line_buffer="d['a")
831 nt.assert_in("abc", matches)
830 nt.assert_in("abc", matches)
832 nt.assert_in("abd", matches)
831 nt.assert_in("abd", matches)
833 nt.assert_not_in("bad", matches)
832 nt.assert_not_in("bad", matches)
834 assert not any(m.endswith(("]", '"', "'")) for m in matches), matches
833 assert not any(m.endswith(("]", '"', "'")) for m in matches), matches
835
834
836 # check escaping and whitespace
835 # check escaping and whitespace
837 ip.user_ns["d"] = {"a\nb": None, "a'b": None, 'a"b': None, "a word": None}
836 ip.user_ns["d"] = {"a\nb": None, "a'b": None, 'a"b': None, "a word": None}
838 _, matches = complete(line_buffer="d['a")
837 _, matches = complete(line_buffer="d['a")
839 nt.assert_in("a\\nb", matches)
838 nt.assert_in("a\\nb", matches)
840 nt.assert_in("a\\'b", matches)
839 nt.assert_in("a\\'b", matches)
841 nt.assert_in('a"b', matches)
840 nt.assert_in('a"b', matches)
842 nt.assert_in("a word", matches)
841 nt.assert_in("a word", matches)
843 assert not any(m.endswith(("]", '"', "'")) for m in matches), matches
842 assert not any(m.endswith(("]", '"', "'")) for m in matches), matches
844
843
845 # - can complete on non-initial word of the string
844 # - can complete on non-initial word of the string
846 _, matches = complete(line_buffer="d['a w")
845 _, matches = complete(line_buffer="d['a w")
847 nt.assert_in("word", matches)
846 nt.assert_in("word", matches)
848
847
849 # - understands quote escaping
848 # - understands quote escaping
850 _, matches = complete(line_buffer="d['a\\'")
849 _, matches = complete(line_buffer="d['a\\'")
851 nt.assert_in("b", matches)
850 nt.assert_in("b", matches)
852
851
853 # - default quoting should work like repr
852 # - default quoting should work like repr
854 _, matches = complete(line_buffer="d[")
853 _, matches = complete(line_buffer="d[")
855 nt.assert_in('"a\'b"', matches)
854 nt.assert_in('"a\'b"', matches)
856
855
857 # - when opening quote with ", possible to match with unescaped apostrophe
856 # - when opening quote with ", possible to match with unescaped apostrophe
858 _, matches = complete(line_buffer="d[\"a'")
857 _, matches = complete(line_buffer="d[\"a'")
859 nt.assert_in("b", matches)
858 nt.assert_in("b", matches)
860
859
861 # need to not split at delims that readline won't split at
860 # need to not split at delims that readline won't split at
862 if "-" not in ip.Completer.splitter.delims:
861 if "-" not in ip.Completer.splitter.delims:
863 ip.user_ns["d"] = {"before-after": None}
862 ip.user_ns["d"] = {"before-after": None}
864 _, matches = complete(line_buffer="d['before-af")
863 _, matches = complete(line_buffer="d['before-af")
865 nt.assert_in("before-after", matches)
864 nt.assert_in("before-after", matches)
866
865
867 def test_dict_key_completion_contexts(self):
866 def test_dict_key_completion_contexts(self):
868 """Test expression contexts in which dict key completion occurs"""
867 """Test expression contexts in which dict key completion occurs"""
869 ip = get_ipython()
868 ip = get_ipython()
870 complete = ip.Completer.complete
869 complete = ip.Completer.complete
871 d = {"abc": None}
870 d = {"abc": None}
872 ip.user_ns["d"] = d
871 ip.user_ns["d"] = d
873
872
874 class C:
873 class C:
875 data = d
874 data = d
876
875
877 ip.user_ns["C"] = C
876 ip.user_ns["C"] = C
878 ip.user_ns["get"] = lambda: d
877 ip.user_ns["get"] = lambda: d
879
878
880 def assert_no_completion(**kwargs):
879 def assert_no_completion(**kwargs):
881 _, matches = complete(**kwargs)
880 _, matches = complete(**kwargs)
882 nt.assert_not_in("abc", matches)
881 nt.assert_not_in("abc", matches)
883 nt.assert_not_in("abc'", matches)
882 nt.assert_not_in("abc'", matches)
884 nt.assert_not_in("abc']", matches)
883 nt.assert_not_in("abc']", matches)
885 nt.assert_not_in("'abc'", matches)
884 nt.assert_not_in("'abc'", matches)
886 nt.assert_not_in("'abc']", matches)
885 nt.assert_not_in("'abc']", matches)
887
886
888 def assert_completion(**kwargs):
887 def assert_completion(**kwargs):
889 _, matches = complete(**kwargs)
888 _, matches = complete(**kwargs)
890 nt.assert_in("'abc'", matches)
889 nt.assert_in("'abc'", matches)
891 nt.assert_not_in("'abc']", matches)
890 nt.assert_not_in("'abc']", matches)
892
891
893 # no completion after string closed, even if reopened
892 # no completion after string closed, even if reopened
894 assert_no_completion(line_buffer="d['a'")
893 assert_no_completion(line_buffer="d['a'")
895 assert_no_completion(line_buffer='d["a"')
894 assert_no_completion(line_buffer='d["a"')
896 assert_no_completion(line_buffer="d['a' + ")
895 assert_no_completion(line_buffer="d['a' + ")
897 assert_no_completion(line_buffer="d['a' + '")
896 assert_no_completion(line_buffer="d['a' + '")
898
897
899 # completion in non-trivial expressions
898 # completion in non-trivial expressions
900 assert_completion(line_buffer="+ d[")
899 assert_completion(line_buffer="+ d[")
901 assert_completion(line_buffer="(d[")
900 assert_completion(line_buffer="(d[")
902 assert_completion(line_buffer="C.data[")
901 assert_completion(line_buffer="C.data[")
903
902
904 # greedy flag
903 # greedy flag
905 def assert_completion(**kwargs):
904 def assert_completion(**kwargs):
906 _, matches = complete(**kwargs)
905 _, matches = complete(**kwargs)
907 nt.assert_in("get()['abc']", matches)
906 nt.assert_in("get()['abc']", matches)
908
907
909 assert_no_completion(line_buffer="get()[")
908 assert_no_completion(line_buffer="get()[")
910 with greedy_completion():
909 with greedy_completion():
911 assert_completion(line_buffer="get()[")
910 assert_completion(line_buffer="get()[")
912 assert_completion(line_buffer="get()['")
911 assert_completion(line_buffer="get()['")
913 assert_completion(line_buffer="get()['a")
912 assert_completion(line_buffer="get()['a")
914 assert_completion(line_buffer="get()['ab")
913 assert_completion(line_buffer="get()['ab")
915 assert_completion(line_buffer="get()['abc")
914 assert_completion(line_buffer="get()['abc")
916
915
917 def test_dict_key_completion_bytes(self):
916 def test_dict_key_completion_bytes(self):
918 """Test handling of bytes in dict key completion"""
917 """Test handling of bytes in dict key completion"""
919 ip = get_ipython()
918 ip = get_ipython()
920 complete = ip.Completer.complete
919 complete = ip.Completer.complete
921
920
922 ip.user_ns["d"] = {"abc": None, b"abd": None}
921 ip.user_ns["d"] = {"abc": None, b"abd": None}
923
922
924 _, matches = complete(line_buffer="d[")
923 _, matches = complete(line_buffer="d[")
925 nt.assert_in("'abc'", matches)
924 nt.assert_in("'abc'", matches)
926 nt.assert_in("b'abd'", matches)
925 nt.assert_in("b'abd'", matches)
927
926
928 if False: # not currently implemented
927 if False: # not currently implemented
929 _, matches = complete(line_buffer="d[b")
928 _, matches = complete(line_buffer="d[b")
930 nt.assert_in("b'abd'", matches)
929 nt.assert_in("b'abd'", matches)
931 nt.assert_not_in("b'abc'", matches)
930 nt.assert_not_in("b'abc'", matches)
932
931
933 _, matches = complete(line_buffer="d[b'")
932 _, matches = complete(line_buffer="d[b'")
934 nt.assert_in("abd", matches)
933 nt.assert_in("abd", matches)
935 nt.assert_not_in("abc", matches)
934 nt.assert_not_in("abc", matches)
936
935
937 _, matches = complete(line_buffer="d[B'")
936 _, matches = complete(line_buffer="d[B'")
938 nt.assert_in("abd", matches)
937 nt.assert_in("abd", matches)
939 nt.assert_not_in("abc", matches)
938 nt.assert_not_in("abc", matches)
940
939
941 _, matches = complete(line_buffer="d['")
940 _, matches = complete(line_buffer="d['")
942 nt.assert_in("abc", matches)
941 nt.assert_in("abc", matches)
943 nt.assert_not_in("abd", matches)
942 nt.assert_not_in("abd", matches)
944
943
945 def test_dict_key_completion_unicode_py3(self):
944 def test_dict_key_completion_unicode_py3(self):
946 """Test handling of unicode in dict key completion"""
945 """Test handling of unicode in dict key completion"""
947 ip = get_ipython()
946 ip = get_ipython()
948 complete = ip.Completer.complete
947 complete = ip.Completer.complete
949
948
950 ip.user_ns["d"] = {"a\u05d0": None}
949 ip.user_ns["d"] = {"a\u05d0": None}
951
950
952 # query using escape
951 # query using escape
953 if sys.platform != "win32":
952 if sys.platform != "win32":
954 # Known failure on Windows
953 # Known failure on Windows
955 _, matches = complete(line_buffer="d['a\\u05d0")
954 _, matches = complete(line_buffer="d['a\\u05d0")
956 nt.assert_in("u05d0", matches) # tokenized after \\
955 nt.assert_in("u05d0", matches) # tokenized after \\
957
956
958 # query using character
957 # query using character
959 _, matches = complete(line_buffer="d['a\u05d0")
958 _, matches = complete(line_buffer="d['a\u05d0")
960 nt.assert_in("a\u05d0", matches)
959 nt.assert_in("a\u05d0", matches)
961
960
962 with greedy_completion():
961 with greedy_completion():
963 # query using escape
962 # query using escape
964 _, matches = complete(line_buffer="d['a\\u05d0")
963 _, matches = complete(line_buffer="d['a\\u05d0")
965 nt.assert_in("d['a\\u05d0']", matches) # tokenized after \\
964 nt.assert_in("d['a\\u05d0']", matches) # tokenized after \\
966
965
967 # query using character
966 # query using character
968 _, matches = complete(line_buffer="d['a\u05d0")
967 _, matches = complete(line_buffer="d['a\u05d0")
969 nt.assert_in("d['a\u05d0']", matches)
968 nt.assert_in("d['a\u05d0']", matches)
970
969
971 @dec.skip_without("numpy")
970 @dec.skip_without("numpy")
972 def test_struct_array_key_completion(self):
971 def test_struct_array_key_completion(self):
973 """Test dict key completion applies to numpy struct arrays"""
972 """Test dict key completion applies to numpy struct arrays"""
974 import numpy
973 import numpy
975
974
976 ip = get_ipython()
975 ip = get_ipython()
977 complete = ip.Completer.complete
976 complete = ip.Completer.complete
978 ip.user_ns["d"] = numpy.array([], dtype=[("hello", "f"), ("world", "f")])
977 ip.user_ns["d"] = numpy.array([], dtype=[("hello", "f"), ("world", "f")])
979 _, matches = complete(line_buffer="d['")
978 _, matches = complete(line_buffer="d['")
980 nt.assert_in("hello", matches)
979 nt.assert_in("hello", matches)
981 nt.assert_in("world", matches)
980 nt.assert_in("world", matches)
982 # complete on the numpy struct itself
981 # complete on the numpy struct itself
983 dt = numpy.dtype(
982 dt = numpy.dtype(
984 [("my_head", [("my_dt", ">u4"), ("my_df", ">u4")]), ("my_data", ">f4", 5)]
983 [("my_head", [("my_dt", ">u4"), ("my_df", ">u4")]), ("my_data", ">f4", 5)]
985 )
984 )
986 x = numpy.zeros(2, dtype=dt)
985 x = numpy.zeros(2, dtype=dt)
987 ip.user_ns["d"] = x[1]
986 ip.user_ns["d"] = x[1]
988 _, matches = complete(line_buffer="d['")
987 _, matches = complete(line_buffer="d['")
989 nt.assert_in("my_head", matches)
988 nt.assert_in("my_head", matches)
990 nt.assert_in("my_data", matches)
989 nt.assert_in("my_data", matches)
991 # complete on a nested level
990 # complete on a nested level
992 with greedy_completion():
991 with greedy_completion():
993 ip.user_ns["d"] = numpy.zeros(2, dtype=dt)
992 ip.user_ns["d"] = numpy.zeros(2, dtype=dt)
994 _, matches = complete(line_buffer="d[1]['my_head']['")
993 _, matches = complete(line_buffer="d[1]['my_head']['")
995 nt.assert_true(any(["my_dt" in m for m in matches]))
994 nt.assert_true(any(["my_dt" in m for m in matches]))
996 nt.assert_true(any(["my_df" in m for m in matches]))
995 nt.assert_true(any(["my_df" in m for m in matches]))
997
996
998 @dec.skip_without("pandas")
997 @dec.skip_without("pandas")
999 def test_dataframe_key_completion(self):
998 def test_dataframe_key_completion(self):
1000 """Test dict key completion applies to pandas DataFrames"""
999 """Test dict key completion applies to pandas DataFrames"""
1001 import pandas
1000 import pandas
1002
1001
1003 ip = get_ipython()
1002 ip = get_ipython()
1004 complete = ip.Completer.complete
1003 complete = ip.Completer.complete
1005 ip.user_ns["d"] = pandas.DataFrame({"hello": [1], "world": [2]})
1004 ip.user_ns["d"] = pandas.DataFrame({"hello": [1], "world": [2]})
1006 _, matches = complete(line_buffer="d['")
1005 _, matches = complete(line_buffer="d['")
1007 nt.assert_in("hello", matches)
1006 nt.assert_in("hello", matches)
1008 nt.assert_in("world", matches)
1007 nt.assert_in("world", matches)
1009
1008
1010 def test_dict_key_completion_invalids(self):
1009 def test_dict_key_completion_invalids(self):
1011 """Smoke test cases dict key completion can't handle"""
1010 """Smoke test cases dict key completion can't handle"""
1012 ip = get_ipython()
1011 ip = get_ipython()
1013 complete = ip.Completer.complete
1012 complete = ip.Completer.complete
1014
1013
1015 ip.user_ns["no_getitem"] = None
1014 ip.user_ns["no_getitem"] = None
1016 ip.user_ns["no_keys"] = []
1015 ip.user_ns["no_keys"] = []
1017 ip.user_ns["cant_call_keys"] = dict
1016 ip.user_ns["cant_call_keys"] = dict
1018 ip.user_ns["empty"] = {}
1017 ip.user_ns["empty"] = {}
1019 ip.user_ns["d"] = {"abc": 5}
1018 ip.user_ns["d"] = {"abc": 5}
1020
1019
1021 _, matches = complete(line_buffer="no_getitem['")
1020 _, matches = complete(line_buffer="no_getitem['")
1022 _, matches = complete(line_buffer="no_keys['")
1021 _, matches = complete(line_buffer="no_keys['")
1023 _, matches = complete(line_buffer="cant_call_keys['")
1022 _, matches = complete(line_buffer="cant_call_keys['")
1024 _, matches = complete(line_buffer="empty['")
1023 _, matches = complete(line_buffer="empty['")
1025 _, matches = complete(line_buffer="name_error['")
1024 _, matches = complete(line_buffer="name_error['")
1026 _, matches = complete(line_buffer="d['\\") # incomplete escape
1025 _, matches = complete(line_buffer="d['\\") # incomplete escape
1027
1026
1028 def test_object_key_completion(self):
1027 def test_object_key_completion(self):
1029 ip = get_ipython()
1028 ip = get_ipython()
1030 ip.user_ns["key_completable"] = KeyCompletable(["qwerty", "qwick"])
1029 ip.user_ns["key_completable"] = KeyCompletable(["qwerty", "qwick"])
1031
1030
1032 _, matches = ip.Completer.complete(line_buffer="key_completable['qw")
1031 _, matches = ip.Completer.complete(line_buffer="key_completable['qw")
1033 nt.assert_in("qwerty", matches)
1032 nt.assert_in("qwerty", matches)
1034 nt.assert_in("qwick", matches)
1033 nt.assert_in("qwick", matches)
1035
1034
1036 def test_class_key_completion(self):
1035 def test_class_key_completion(self):
1037 ip = get_ipython()
1036 ip = get_ipython()
1038 NamedInstanceClass("qwerty")
1037 NamedInstanceClass("qwerty")
1039 NamedInstanceClass("qwick")
1038 NamedInstanceClass("qwick")
1040 ip.user_ns["named_instance_class"] = NamedInstanceClass
1039 ip.user_ns["named_instance_class"] = NamedInstanceClass
1041
1040
1042 _, matches = ip.Completer.complete(line_buffer="named_instance_class['qw")
1041 _, matches = ip.Completer.complete(line_buffer="named_instance_class['qw")
1043 nt.assert_in("qwerty", matches)
1042 nt.assert_in("qwerty", matches)
1044 nt.assert_in("qwick", matches)
1043 nt.assert_in("qwick", matches)
1045
1044
1046 def test_tryimport(self):
1045 def test_tryimport(self):
1047 """
1046 """
1048 Test that try-import don't crash on trailing dot, and import modules before
1047 Test that try-import don't crash on trailing dot, and import modules before
1049 """
1048 """
1050 from IPython.core.completerlib import try_import
1049 from IPython.core.completerlib import try_import
1051
1050
1052 assert try_import("IPython.")
1051 assert try_import("IPython.")
1053
1052
1054 def test_aimport_module_completer(self):
1053 def test_aimport_module_completer(self):
1055 ip = get_ipython()
1054 ip = get_ipython()
1056 _, matches = ip.complete("i", "%aimport i")
1055 _, matches = ip.complete("i", "%aimport i")
1057 nt.assert_in("io", matches)
1056 nt.assert_in("io", matches)
1058 nt.assert_not_in("int", matches)
1057 nt.assert_not_in("int", matches)
1059
1058
1060 def test_nested_import_module_completer(self):
1059 def test_nested_import_module_completer(self):
1061 ip = get_ipython()
1060 ip = get_ipython()
1062 _, matches = ip.complete(None, "import IPython.co", 17)
1061 _, matches = ip.complete(None, "import IPython.co", 17)
1063 nt.assert_in("IPython.core", matches)
1062 nt.assert_in("IPython.core", matches)
1064 nt.assert_not_in("import IPython.core", matches)
1063 nt.assert_not_in("import IPython.core", matches)
1065 nt.assert_not_in("IPython.display", matches)
1064 nt.assert_not_in("IPython.display", matches)
1066
1065
1067 def test_import_module_completer(self):
1066 def test_import_module_completer(self):
1068 ip = get_ipython()
1067 ip = get_ipython()
1069 _, matches = ip.complete("i", "import i")
1068 _, matches = ip.complete("i", "import i")
1070 nt.assert_in("io", matches)
1069 nt.assert_in("io", matches)
1071 nt.assert_not_in("int", matches)
1070 nt.assert_not_in("int", matches)
1072
1071
1073 def test_from_module_completer(self):
1072 def test_from_module_completer(self):
1074 ip = get_ipython()
1073 ip = get_ipython()
1075 _, matches = ip.complete("B", "from io import B", 16)
1074 _, matches = ip.complete("B", "from io import B", 16)
1076 nt.assert_in("BytesIO", matches)
1075 nt.assert_in("BytesIO", matches)
1077 nt.assert_not_in("BaseException", matches)
1076 nt.assert_not_in("BaseException", matches)
1078
1077
1079 def test_snake_case_completion(self):
1078 def test_snake_case_completion(self):
1080 ip = get_ipython()
1079 ip = get_ipython()
1081 ip.Completer.use_jedi = False
1080 ip.Completer.use_jedi = False
1082 ip.user_ns["some_three"] = 3
1081 ip.user_ns["some_three"] = 3
1083 ip.user_ns["some_four"] = 4
1082 ip.user_ns["some_four"] = 4
1084 _, matches = ip.complete("s_", "print(s_f")
1083 _, matches = ip.complete("s_", "print(s_f")
1085 nt.assert_in("some_three", matches)
1084 nt.assert_in("some_three", matches)
1086 nt.assert_in("some_four", matches)
1085 nt.assert_in("some_four", matches)
1087
1086
1088 def test_mix_terms(self):
1087 def test_mix_terms(self):
1089 ip = get_ipython()
1088 ip = get_ipython()
1090 from textwrap import dedent
1089 from textwrap import dedent
1091
1090
1092 ip.Completer.use_jedi = False
1091 ip.Completer.use_jedi = False
1093 ip.ex(
1092 ip.ex(
1094 dedent(
1093 dedent(
1095 """
1094 """
1096 class Test:
1095 class Test:
1097 def meth(self, meth_arg1):
1096 def meth(self, meth_arg1):
1098 print("meth")
1097 print("meth")
1099
1098
1100 def meth_1(self, meth1_arg1, meth1_arg2):
1099 def meth_1(self, meth1_arg1, meth1_arg2):
1101 print("meth1")
1100 print("meth1")
1102
1101
1103 def meth_2(self, meth2_arg1, meth2_arg2):
1102 def meth_2(self, meth2_arg1, meth2_arg2):
1104 print("meth2")
1103 print("meth2")
1105 test = Test()
1104 test = Test()
1106 """
1105 """
1107 )
1106 )
1108 )
1107 )
1109 _, matches = ip.complete(None, "test.meth(")
1108 _, matches = ip.complete(None, "test.meth(")
1110 nt.assert_in("meth_arg1=", matches)
1109 nt.assert_in("meth_arg1=", matches)
1111 nt.assert_not_in("meth2_arg1=", matches)
1110 nt.assert_not_in("meth2_arg1=", matches)
@@ -1,45 +1,46 b''
1 include README.rst
1 include README.rst
2 include COPYING.rst
2 include COPYING.rst
3 include LICENSE
3 include LICENSE
4 include setupbase.py
4 include setupbase.py
5 include setupegg.py
5 include setupegg.py
6 include MANIFEST.in
6 include MANIFEST.in
7 include pytest.ini
7 include pytest.ini
8 include mypy.ini
8 include .mailmap
9 include .mailmap
9
10
10 recursive-exclude tools *
11 recursive-exclude tools *
11 exclude tools
12 exclude tools
12 exclude CONTRIBUTING.md
13 exclude CONTRIBUTING.md
13 exclude .editorconfig
14 exclude .editorconfig
14
15
15 graft setupext
16 graft setupext
16
17
17 graft scripts
18 graft scripts
18
19
19 # Load main dir but exclude things we don't want in the distro
20 # Load main dir but exclude things we don't want in the distro
20 graft IPython
21 graft IPython
21
22
22 # Documentation
23 # Documentation
23 graft docs
24 graft docs
24 exclude docs/\#*
25 exclude docs/\#*
25 exclude docs/man/*.1.gz
26 exclude docs/man/*.1.gz
26
27
27 exclude .git-blame-ignore-revs
28 exclude .git-blame-ignore-revs
28
29
29 # Examples
30 # Examples
30 graft examples
31 graft examples
31
32
32 # docs subdirs we want to skip
33 # docs subdirs we want to skip
33 prune docs/build
34 prune docs/build
34 prune docs/gh-pages
35 prune docs/gh-pages
35 prune docs/dist
36 prune docs/dist
36
37
37 # Patterns to exclude from any directory
38 # Patterns to exclude from any directory
38 global-exclude *~
39 global-exclude *~
39 global-exclude *.flc
40 global-exclude *.flc
40 global-exclude *.yml
41 global-exclude *.yml
41 global-exclude *.pyc
42 global-exclude *.pyc
42 global-exclude *.pyo
43 global-exclude *.pyo
43 global-exclude .dircopy.log
44 global-exclude .dircopy.log
44 global-exclude .git
45 global-exclude .git
45 global-exclude .ipynb_checkpoints
46 global-exclude .ipynb_checkpoints
General Comments 0
You need to be logged in to leave comments. Login now