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