##// END OF EJS Templates
Merge pull request #10285 from Carreau/deduplicate-completions...
Fernando Perez -
r23359:9f622df4 merge
parent child Browse files
Show More
@@ -1,1760 +1,1796 b''
1 1 # encoding: utf-8
2 2 """Completion for IPython.
3 3
4 4 This module started as fork of the rlcompleter module in the Python standard
5 5 library. The original enhancements made to rlcompleter have been sent
6 6 upstream and were accepted as of Python 2.3,
7 7
8 8 This module now support a wide variety of completion mechanism both available
9 9 for normal classic Python code, as well as completer for IPython specific
10 10 Syntax like magics.
11 11
12 12 Experimental
13 13 ============
14 14
15 15 Starting with IPython 6.0, this module can make use of the Jedi library to
16 16 generate completions both using static analysis of the code, and dynamically
17 17 inspecting multiple namespaces. The APIs attached to this new mechanism is
18 18 unstable and will raise unless use in an :any:`provisionalcompleter` context
19 19 manager.
20 20
21 21 You will find that the following are experimental:
22 22
23 23 - :any:`provisionalcompleter`
24 24 - :any:`IPCompleter.completions`
25 25 - :any:`Completion`
26 26 - :any:`rectify_completions`
27 27
28 28 .. note::
29 29
30 30 better name for :any:`rectify_completions` ?
31 31
32 32 We welcome any feedback on these new API, and we also encourage you to try this
33 33 module in debug mode (start IPython with ``--Completer.debug=True``) in order
34 34 to have extra logging information is :any:`jedi` is crashing, or if current
35 35 IPython completer pending deprecations are returning results not yet handled
36 36 by :any:`jedi`.
37 37
38 38 Using Jedi for tab completion allow snippets like the following to work without
39 39 having to execute any code:
40 40
41 41 >>> myvar = ['hello', 42]
42 42 ... myvar[1].bi<tab>
43 43
44 44 Tab completion will be able to infer that ``myvar[1]`` is a real number without
45 45 executing any code unlike the previously available ``IPCompleter.greedy``
46 46 option.
47 47
48 48 Be sure to update :any:`jedi` to the latest stable version or to try the
49 49 current development version to get better completions.
50 50 """
51 51
52 52 # skip module docstests
53 53 skip_doctest = True
54 54
55 55 # Copyright (c) IPython Development Team.
56 56 # Distributed under the terms of the Modified BSD License.
57 57 #
58 58 # Some of this code originated from rlcompleter in the Python standard library
59 59 # Copyright (C) 2001 Python Software Foundation, www.python.org
60 60
61 61
62 62 import __main__
63 63 import builtins as builtin_mod
64 64 import glob
65 65 import time
66 66 import inspect
67 67 import itertools
68 68 import keyword
69 69 import os
70 70 import re
71 71 import sys
72 72 import unicodedata
73 73 import string
74 74 import warnings
75 75
76 76 from contextlib import contextmanager
77 77 from importlib import import_module
78 78 from typing import Iterator, List
79 79 from types import SimpleNamespace
80 80
81 81 from traitlets.config.configurable import Configurable
82 82 from IPython.core.error import TryNext
83 83 from IPython.core.inputsplitter import ESC_MAGIC
84 84 from IPython.core.latex_symbols import latex_symbols, reverse_latex_symbol
85 85 from IPython.utils import generics
86 86 from IPython.utils.dir2 import dir2, get_real_method
87 87 from IPython.utils.process import arg_split
88 88 from IPython.utils.py3compat import cast_unicode_py2
89 89 from traitlets import Bool, Enum, observe, Int
90 90
91 91 try:
92 92 import jedi
93 93 import jedi.api.helpers
94 94 JEDI_INSTALLED = True
95 95 except ImportError:
96 96 JEDI_INSTALLED = False
97 97 #-----------------------------------------------------------------------------
98 98 # Globals
99 99 #-----------------------------------------------------------------------------
100 100
101 101 # Public API
102 102 __all__ = ['Completer','IPCompleter']
103 103
104 104 if sys.platform == 'win32':
105 105 PROTECTABLES = ' '
106 106 else:
107 107 PROTECTABLES = ' ()[]{}?=\\|;:\'#*"^&'
108 108
109 109
110 110 _deprecation_readline_sentinel = object()
111 111
112 112
113 113 class ProvisionalCompleterWarning(FutureWarning):
114 114 """
115 115 Exception raise by an experimental feature in this module.
116 116
117 117 Wrap code in :any:`provisionalcompleter` context manager if you
118 118 are certain you want to use an unstable feature.
119 119 """
120 120 pass
121 121
122 122 warnings.filterwarnings('error', category=ProvisionalCompleterWarning)
123 123
124 124 @contextmanager
125 125 def provisionalcompleter(action='ignore'):
126 126 """
127 127
128 128
129 129 This contest manager has to be used in any place where unstable completer
130 130 behavior and API may be called.
131 131
132 132 >>> with provisionalcompleter():
133 133 ... completer.do_experimetal_things() # works
134 134
135 135 >>> completer.do_experimental_things() # raises.
136 136
137 137 .. note:: Unstable
138 138
139 139 By using this context manager you agree that the API in use may change
140 140 without warning, and that you won't complain if they do so.
141 141
142 142 You also understand that if the API is not to you liking you should report
143 143 a bug to explain your use case upstream and improve the API and will loose
144 144 credibility if you complain after the API is make stable.
145 145
146 146 We'll be happy to get your feedback , feature request and improvement on
147 147 any of the unstable APIs !
148 148 """
149 149 with warnings.catch_warnings():
150 150 warnings.filterwarnings(action, category=ProvisionalCompleterWarning)
151 151 yield
152 152
153 153
154 154 def has_open_quotes(s):
155 155 """Return whether a string has open quotes.
156 156
157 157 This simply counts whether the number of quote characters of either type in
158 158 the string is odd.
159 159
160 160 Returns
161 161 -------
162 162 If there is an open quote, the quote character is returned. Else, return
163 163 False.
164 164 """
165 165 # We check " first, then ', so complex cases with nested quotes will get
166 166 # the " to take precedence.
167 167 if s.count('"') % 2:
168 168 return '"'
169 169 elif s.count("'") % 2:
170 170 return "'"
171 171 else:
172 172 return False
173 173
174 174
175 175 def protect_filename(s):
176 176 """Escape a string to protect certain characters."""
177 177 if set(s) & set(PROTECTABLES):
178 178 if sys.platform == "win32":
179 179 return '"' + s + '"'
180 180 else:
181 181 return "".join(("\\" + c if c in PROTECTABLES else c) for c in s)
182 182 else:
183 183 return s
184 184
185 185
186 186 def expand_user(path):
187 187 """Expand ``~``-style usernames in strings.
188 188
189 189 This is similar to :func:`os.path.expanduser`, but it computes and returns
190 190 extra information that will be useful if the input was being used in
191 191 computing completions, and you wish to return the completions with the
192 192 original '~' instead of its expanded value.
193 193
194 194 Parameters
195 195 ----------
196 196 path : str
197 197 String to be expanded. If no ~ is present, the output is the same as the
198 198 input.
199 199
200 200 Returns
201 201 -------
202 202 newpath : str
203 203 Result of ~ expansion in the input path.
204 204 tilde_expand : bool
205 205 Whether any expansion was performed or not.
206 206 tilde_val : str
207 207 The value that ~ was replaced with.
208 208 """
209 209 # Default values
210 210 tilde_expand = False
211 211 tilde_val = ''
212 212 newpath = path
213 213
214 214 if path.startswith('~'):
215 215 tilde_expand = True
216 216 rest = len(path)-1
217 217 newpath = os.path.expanduser(path)
218 218 if rest:
219 219 tilde_val = newpath[:-rest]
220 220 else:
221 221 tilde_val = newpath
222 222
223 223 return newpath, tilde_expand, tilde_val
224 224
225 225
226 226 def compress_user(path, tilde_expand, tilde_val):
227 227 """Does the opposite of expand_user, with its outputs.
228 228 """
229 229 if tilde_expand:
230 230 return path.replace(tilde_val, '~')
231 231 else:
232 232 return path
233 233
234 234
235 235 def completions_sorting_key(word):
236 236 """key for sorting completions
237 237
238 238 This does several things:
239 239
240 240 - Lowercase all completions, so they are sorted alphabetically with
241 241 upper and lower case words mingled
242 242 - Demote any completions starting with underscores to the end
243 243 - Insert any %magic and %%cellmagic completions in the alphabetical order
244 244 by their name
245 245 """
246 246 # Case insensitive sort
247 247 word = word.lower()
248 248
249 249 prio1, prio2 = 0, 0
250 250
251 251 if word.startswith('__'):
252 252 prio1 = 2
253 253 elif word.startswith('_'):
254 254 prio1 = 1
255 255
256 256 if word.endswith('='):
257 257 prio1 = -1
258 258
259 259 if word.startswith('%%'):
260 260 # If there's another % in there, this is something else, so leave it alone
261 261 if not "%" in word[2:]:
262 262 word = word[2:]
263 263 prio2 = 2
264 264 elif word.startswith('%'):
265 265 if not "%" in word[1:]:
266 266 word = word[1:]
267 267 prio2 = 1
268 268
269 269 return prio1, word, prio2
270 270
271 271
272 272 class _FakeJediCompletion:
273 273 """
274 274 This is a workaround to communicate to the UI that Jedi has crashed and to
275 275 report a bug. Will be used only id :any:`IPCompleter.debug` is set to true.
276 276
277 277 Added in IPython 6.0 so should likely be removed for 7.0
278 278
279 279 """
280 280
281 281 def __init__(self, name):
282 282
283 283 self.name = name
284 284 self.complete = name
285 285 self.type = 'crashed'
286 286 self.name_with_symbols = name
287 287
288 288 def __repr__(self):
289 289 return '<Fake completion object jedi has crashed>'
290 290
291 291
292 292 class Completion:
293 293 """
294 294 Completion object used and return by IPython completers.
295 295
296 296 .. warning:: Unstable
297 297
298 298 This function is unstable, API may change without warning.
299 299 It will also raise unless use in proper context manager.
300 300
301 301 This act as a middle ground :any:`Completion` object between the
302 302 :any:`jedi.api.classes.Completion` object and the Prompt Toolkit completion
303 303 object. While Jedi need a lot of information about evaluator and how the
304 304 code should be ran/inspected, PromptToolkit (and other frontend) mostly
305 305 need user facing information.
306 306
307 307 - Which range should be replaced replaced by what.
308 308 - Some metadata (like completion type), or meta informations to displayed to
309 309 the use user.
310 310
311 311 For debugging purpose we can also store the origin of the completion (``jedi``,
312 312 ``IPython.python_matches``, ``IPython.magics_matches``...).
313 313 """
314 314
315 315 def __init__(self, start: int, end: int, text: str, *, type: str=None, _origin=''):
316 316 warnings.warn("``Completion`` is a provisional API (as of IPython 6.0). "
317 317 "It may change without warnings. "
318 318 "Use in corresponding context manager.",
319 319 category=ProvisionalCompleterWarning, stacklevel=2)
320 320
321 321 self.start = start
322 322 self.end = end
323 323 self.text = text
324 324 self.type = type
325 325 self._origin = _origin
326 326
327 327 def __repr__(self):
328 328 return '<Completion start=%s end=%s text=%r type=%r>' % (self.start, self.end, self.text, self.type or '?')
329 329
330 330 def __eq__(self, other)->Bool:
331 331 """
332 332 Equality and hash do not hash the type (as some completer may not be
333 333 able to infer the type), but are use to (partially) de-duplicate
334 334 completion.
335 335
336 336 Completely de-duplicating completion is a bit tricker that just
337 337 comparing as it depends on surrounding text, which Completions are not
338 338 aware of.
339 339 """
340 340 return self.start == other.start and \
341 341 self.end == other.end and \
342 342 self.text == other.text
343 343
344 344 def __hash__(self):
345 345 return hash((self.start, self.end, self.text))
346 346
347
347 348 _IC = Iterator[Completion]
348 349
349 def rectify_completions(text:str, completion:_IC, *, _debug=False)->_IC:
350
351 def _deduplicate_completions(text: str, completions: _IC)-> _IC:
350 352 """
351 Rectify a set of completion to all have the same ``start`` and ``end``
353 Deduplicate a set of completions.
354
355 .. warning:: Unstable
356
357 This function is unstable, API may change without warning.
358
359 Parameters
360 ----------
361 text: str
362 text that should be completed.
363 completions: Iterator[Completion]
364 iterator over the completions to deduplicate
365
366
367 Completions coming from multiple sources, may be different but end up having
368 the same effect when applied to ``text``. If this is the case, this will
369 consider completions as equal and only emit the first encountered.
370
371 Not folded in `completions()` yet for debugging purpose, and to detect when
372 the IPython completer does return things that Jedi does not, but should be
373 at some point.
374 """
375 completions = list(completions)
376 if not completions:
377 return
378
379 new_start = min(c.start for c in completions)
380 new_end = max(c.end for c in completions)
381
382 seen = set()
383 for c in completions:
384 new_text = text[new_start:c.start] + c.text + text[c.end:new_end]
385 if new_text not in seen:
386 yield c
387 seen.add(new_text)
388
389
390 def rectify_completions(text: str, completions: _IC, *, _debug=False)->_IC:
391 """
392 Rectify a set of completions to all have the same ``start`` and ``end``
352 393
353 394 .. warning:: Unstable
354 395
355 396 This function is unstable, API may change without warning.
356 397 It will also raise unless use in proper context manager.
357 398
358 399 Parameters
359 400 ----------
360 401 text: str
361 402 text that should be completed.
362 completion: Iterator[Completion]
403 completions: Iterator[Completion]
363 404 iterator over the completions to rectify
364 405
365 406
366 407 :any:`jedi.api.classes.Completion` s returned by Jedi may not have the same start and end, though
367 408 the Jupyter Protocol requires them to behave like so. This will readjust
368 409 the completion to have the same ``start`` and ``end` by padding both
369 410 extremities with surrounding text.
370 411
371 412 During stabilisation should support a ``_debug`` option to log which
372 413 completion are return by the IPython completer and not found in Jedi in
373 414 order to make upstream bug report.
374 415 """
375 416 warnings.warn("`rectify_completions` is a provisional API (as of IPython 6.0). "
376 417 "It may change without warnings. "
377 418 "Use in corresponding context manager.",
378 419 category=ProvisionalCompleterWarning, stacklevel=2)
379 420
380 421 completions = list(completion)
381 422 if not completions:
382 423 return
383 424 starts = (c.start for c in completions)
384 425 ends = (c.end for c in completions)
385 426
386 427 new_start = min(starts)
387 428 new_end = max(ends)
388 429
389 430 seen_jedi = set()
390 431 seen_python_matches = set()
391 432 for c in completions:
392 433 new_text = text[new_start:c.start] + c.text + text[c.end:new_end]
393 434 if c._origin == 'jedi':
394 435 seen_jedi.add(new_text)
395 436 elif c._origin == 'IPCompleter.python_matches':
396 437 seen_python_matches.add(new_text)
397 438 yield Completion(new_start, new_end, new_text, type=c.type, _origin=c._origin)
398 439 diff = seen_python_matches.difference(seen_jedi)
399 440 if diff and _debug:
400 441 print('IPython.python matches have extras:', diff)
401 442
402 443
403 444 if sys.platform == 'win32':
404 445 DELIMS = ' \t\n`!@#$^&*()=+[{]}|;\'",<>?'
405 446 else:
406 447 DELIMS = ' \t\n`!@#$^&*()=+[{]}\\|;:\'",<>?'
407 448
408 449 GREEDY_DELIMS = ' =\r\n'
409 450
410 451
411 452 class CompletionSplitter(object):
412 453 """An object to split an input line in a manner similar to readline.
413 454
414 455 By having our own implementation, we can expose readline-like completion in
415 456 a uniform manner to all frontends. This object only needs to be given the
416 457 line of text to be split and the cursor position on said line, and it
417 458 returns the 'word' to be completed on at the cursor after splitting the
418 459 entire line.
419 460
420 461 What characters are used as splitting delimiters can be controlled by
421 462 setting the ``delims`` attribute (this is a property that internally
422 463 automatically builds the necessary regular expression)"""
423 464
424 465 # Private interface
425 466
426 467 # A string of delimiter characters. The default value makes sense for
427 468 # IPython's most typical usage patterns.
428 469 _delims = DELIMS
429 470
430 471 # The expression (a normal string) to be compiled into a regular expression
431 472 # for actual splitting. We store it as an attribute mostly for ease of
432 473 # debugging, since this type of code can be so tricky to debug.
433 474 _delim_expr = None
434 475
435 476 # The regular expression that does the actual splitting
436 477 _delim_re = None
437 478
438 479 def __init__(self, delims=None):
439 480 delims = CompletionSplitter._delims if delims is None else delims
440 481 self.delims = delims
441 482
442 483 @property
443 484 def delims(self):
444 485 """Return the string of delimiter characters."""
445 486 return self._delims
446 487
447 488 @delims.setter
448 489 def delims(self, delims):
449 490 """Set the delimiters for line splitting."""
450 491 expr = '[' + ''.join('\\'+ c for c in delims) + ']'
451 492 self._delim_re = re.compile(expr)
452 493 self._delims = delims
453 494 self._delim_expr = expr
454 495
455 496 def split_line(self, line, cursor_pos=None):
456 497 """Split a line of text with a cursor at the given position.
457 498 """
458 499 l = line if cursor_pos is None else line[:cursor_pos]
459 500 return self._delim_re.split(l)[-1]
460 501
461 502
462 503
463 504 class Completer(Configurable):
464 505
465 506 greedy = Bool(False,
466 507 help="""Activate greedy completion
467 508 PENDING DEPRECTION. this is now mostly taken care of with Jedi.
468 509
469 510 This will enable completion on elements of lists, results of function calls, etc.,
470 511 but can be unsafe because the code is actually evaluated on TAB.
471 512 """
472 513 ).tag(config=True)
473 514
474 515 use_jedi = Bool(default_value=JEDI_INSTALLED,
475 516 help="Experimental: Use Jedi to generate autocompletions. "
476 517 "Default to True if jedi is installed").tag(config=True)
477 518
478 519 jedi_compute_type_timeout = Int(default_value=400,
479 520 help="""Experimental: restrict time (in milliseconds) during which Jedi can compute types.
480 521 Set to 0 to stop computing types. Non-zero value lower than 100ms may hurt
481 522 performance by preventing jedi to build its cache.
482 523 """).tag(config=True)
483 524
484 525 debug = Bool(default_value=False,
485 526 help='Enable debug for the Completer. Mostly print extra '
486 527 'information for experimental jedi integration.')\
487 528 .tag(config=True)
488 529
489 530
490 531 def __init__(self, namespace=None, global_namespace=None, **kwargs):
491 532 """Create a new completer for the command line.
492 533
493 534 Completer(namespace=ns, global_namespace=ns2) -> completer instance.
494 535
495 536 If unspecified, the default namespace where completions are performed
496 537 is __main__ (technically, __main__.__dict__). Namespaces should be
497 538 given as dictionaries.
498 539
499 540 An optional second namespace can be given. This allows the completer
500 541 to handle cases where both the local and global scopes need to be
501 542 distinguished.
502 543 """
503 544
504 545 # Don't bind to namespace quite yet, but flag whether the user wants a
505 546 # specific namespace or to use __main__.__dict__. This will allow us
506 547 # to bind to __main__.__dict__ at completion time, not now.
507 548 if namespace is None:
508 549 self.use_main_ns = True
509 550 else:
510 551 self.use_main_ns = False
511 552 self.namespace = namespace
512 553
513 554 # The global namespace, if given, can be bound directly
514 555 if global_namespace is None:
515 556 self.global_namespace = {}
516 557 else:
517 558 self.global_namespace = global_namespace
518 559
519 560 super(Completer, self).__init__(**kwargs)
520 561
521 562 def complete(self, text, state):
522 563 """Return the next possible completion for 'text'.
523 564
524 565 This is called successively with state == 0, 1, 2, ... until it
525 566 returns None. The completion should begin with 'text'.
526 567
527 568 """
528 569 if self.use_main_ns:
529 570 self.namespace = __main__.__dict__
530 571
531 572 if state == 0:
532 573 if "." in text:
533 574 self.matches = self.attr_matches(text)
534 575 else:
535 576 self.matches = self.global_matches(text)
536 577 try:
537 578 return self.matches[state]
538 579 except IndexError:
539 580 return None
540 581
541 582 def global_matches(self, text):
542 583 """Compute matches when text is a simple name.
543 584
544 585 Return a list of all keywords, built-in functions and names currently
545 586 defined in self.namespace or self.global_namespace that match.
546 587
547 588 """
548 589 matches = []
549 590 match_append = matches.append
550 591 n = len(text)
551 592 for lst in [keyword.kwlist,
552 593 builtin_mod.__dict__.keys(),
553 594 self.namespace.keys(),
554 595 self.global_namespace.keys()]:
555 596 for word in lst:
556 597 if word[:n] == text and word != "__builtins__":
557 598 match_append(word)
558 599 return [cast_unicode_py2(m) for m in matches]
559 600
560 601 def attr_matches(self, text):
561 602 """Compute matches when text contains a dot.
562 603
563 604 Assuming the text is of the form NAME.NAME....[NAME], and is
564 605 evaluatable in self.namespace or self.global_namespace, it will be
565 606 evaluated and its attributes (as revealed by dir()) are used as
566 607 possible completions. (For class instances, class members are are
567 608 also considered.)
568 609
569 610 WARNING: this can still invoke arbitrary C code, if an object
570 611 with a __getattr__ hook is evaluated.
571 612
572 613 """
573 614
574 615 # Another option, seems to work great. Catches things like ''.<tab>
575 616 m = re.match(r"(\S+(\.\w+)*)\.(\w*)$", text)
576 617
577 618 if m:
578 619 expr, attr = m.group(1, 3)
579 620 elif self.greedy:
580 621 m2 = re.match(r"(.+)\.(\w*)$", self.line_buffer)
581 622 if not m2:
582 623 return []
583 624 expr, attr = m2.group(1,2)
584 625 else:
585 626 return []
586 627
587 628 try:
588 629 obj = eval(expr, self.namespace)
589 630 except:
590 631 try:
591 632 obj = eval(expr, self.global_namespace)
592 633 except:
593 634 return []
594 635
595 636 if self.limit_to__all__ and hasattr(obj, '__all__'):
596 637 words = get__all__entries(obj)
597 638 else:
598 639 words = dir2(obj)
599 640
600 641 try:
601 642 words = generics.complete_object(obj, words)
602 643 except TryNext:
603 644 pass
604 645 except AssertionError:
605 646 raise
606 647 except Exception:
607 648 # Silence errors from completion function
608 649 #raise # dbg
609 650 pass
610 651 # Build match list to return
611 652 n = len(attr)
612 653 return [u"%s.%s" % (expr, w) for w in words if w[:n] == attr ]
613 654
614 655
615 656 def get__all__entries(obj):
616 657 """returns the strings in the __all__ attribute"""
617 658 try:
618 659 words = getattr(obj, '__all__')
619 660 except:
620 661 return []
621 662
622 663 return [cast_unicode_py2(w) for w in words if isinstance(w, str)]
623 664
624 665
625 666 def match_dict_keys(keys: List[str], prefix: str, delims: str):
626 667 """Used by dict_key_matches, matching the prefix to a list of keys
627 668
628 669 Parameters
629 670 ==========
630 671 keys:
631 672 list of keys in dictionary currently being completed.
632 673 prefix:
633 674 Part of the text already typed by the user. e.g. `mydict[b'fo`
634 675 delims:
635 676 String of delimiters to consider when finding the current key.
636 677
637 678 Returns
638 679 =======
639 680
640 681 A tuple of three elements: ``quote``, ``token_start``, ``matched``, with
641 682 ``quote`` being the quote that need to be used to close current string.
642 683 ``token_start`` the position where the replacement should start occurring,
643 684 ``matches`` a list of replacement/completion
644 685
645 686 """
646 687 if not prefix:
647 688 return None, 0, [repr(k) for k in keys
648 689 if isinstance(k, (str, bytes))]
649 690 quote_match = re.search('["\']', prefix)
650 691 quote = quote_match.group()
651 692 try:
652 693 prefix_str = eval(prefix + quote, {})
653 694 except Exception:
654 695 return None, 0, []
655 696
656 697 pattern = '[^' + ''.join('\\' + c for c in delims) + ']*$'
657 698 token_match = re.search(pattern, prefix, re.UNICODE)
658 699 token_start = token_match.start()
659 700 token_prefix = token_match.group()
660 701
661 702 matched = []
662 703 for key in keys:
663 704 try:
664 705 if not key.startswith(prefix_str):
665 706 continue
666 707 except (AttributeError, TypeError, UnicodeError):
667 708 # Python 3+ TypeError on b'a'.startswith('a') or vice-versa
668 709 continue
669 710
670 711 # reformat remainder of key to begin with prefix
671 712 rem = key[len(prefix_str):]
672 713 # force repr wrapped in '
673 714 rem_repr = repr(rem + '"') if isinstance(rem, str) else repr(rem + b'"')
674 715 if rem_repr.startswith('u') and prefix[0] not in 'uU':
675 716 # Found key is unicode, but prefix is Py2 string.
676 717 # Therefore attempt to interpret key as string.
677 718 try:
678 719 rem_repr = repr(rem.encode('ascii') + '"')
679 720 except UnicodeEncodeError:
680 721 continue
681 722
682 723 rem_repr = rem_repr[1 + rem_repr.index("'"):-2]
683 724 if quote == '"':
684 725 # The entered prefix is quoted with ",
685 726 # but the match is quoted with '.
686 727 # A contained " hence needs escaping for comparison:
687 728 rem_repr = rem_repr.replace('"', '\\"')
688 729
689 730 # then reinsert prefix from start of token
690 731 matched.append('%s%s' % (token_prefix, rem_repr))
691 732 return quote, token_start, matched
692 733
693 734
694 735 def cursor_to_position(text:int, line:int, column:int)->int:
695 736 """
696 737
697 738 Convert the (line,column) position of the cursor in text to an offset in a
698 739 string.
699 740
700 741 Parameter
701 742 ---------
702 743
703 744 text : str
704 745 The text in which to calculate the cursor offset
705 746 line : int
706 747 Line of the cursor; 0-indexed
707 748 column : int
708 749 Column of the cursor 0-indexed
709 750
710 751 Return
711 752 ------
712 753 Position of the cursor in ``text``, 0-indexed.
713 754
714 755 See Also
715 756 --------
716 757 position_to_cursor: reciprocal of this function
717 758
718 759 """
719 760 lines = text.split('\n')
720 761 assert line <= len(lines), '{} <= {}'.format(str(line), str(len(lines)))
721 762
722 763 return sum(len(l) + 1 for l in lines[:line]) + column
723 764
724 765 def position_to_cursor(text:str, offset:int)->(int, int):
725 766 """
726 767 Convert the position of the cursor in text (0 indexed) to a line
727 768 number(0-indexed) and a column number (0-indexed) pair
728 769
729 770 Position should be a valid position in ``text``.
730 771
731 772 Parameter
732 773 ---------
733 774
734 775 text : str
735 776 The text in which to calculate the cursor offset
736 777 offset : int
737 778 Position of the cursor in ``text``, 0-indexed.
738 779
739 780 Return
740 781 ------
741 782 (line, column) : (int, int)
742 783 Line of the cursor; 0-indexed, column of the cursor 0-indexed
743 784
744 785
745 786 See Also
746 787 --------
747 788 cursor_to_position : reciprocal of this function
748 789
749 790
750 791 """
751 792
752 793 assert 0 < offset <= len(text) , "0 < %s <= %s" % (offset , len(text))
753 794
754 795 before = text[:offset]
755 796 blines = before.split('\n') # ! splitnes trim trailing \n
756 797 line = before.count('\n')
757 798 col = len(blines[-1])
758 799 return line, col
759 800
760 801
761 802 def _safe_isinstance(obj, module, class_name):
762 803 """Checks if obj is an instance of module.class_name if loaded
763 804 """
764 805 return (module in sys.modules and
765 806 isinstance(obj, getattr(import_module(module), class_name)))
766 807
767 808
768 809 def back_unicode_name_matches(text):
769 810 u"""Match unicode characters back to unicode name
770 811
771 812 This does ``β˜ƒ`` -> ``\\snowman``
772 813
773 814 Note that snowman is not a valid python3 combining character but will be expanded.
774 815 Though it will not recombine back to the snowman character by the completion machinery.
775 816
776 817 This will not either back-complete standard sequences like \\n, \\b ...
777 818
778 819 Used on Python 3 only.
779 820 """
780 821 if len(text)<2:
781 822 return u'', ()
782 823 maybe_slash = text[-2]
783 824 if maybe_slash != '\\':
784 825 return u'', ()
785 826
786 827 char = text[-1]
787 828 # no expand on quote for completion in strings.
788 829 # nor backcomplete standard ascii keys
789 830 if char in string.ascii_letters or char in ['"',"'"]:
790 831 return u'', ()
791 832 try :
792 833 unic = unicodedata.name(char)
793 834 return '\\'+char,['\\'+unic]
794 835 except KeyError:
795 836 pass
796 837 return u'', ()
797 838
798 839 def back_latex_name_matches(text:str):
799 840 """Match latex characters back to unicode name
800 841
801 842 This does ``\\β„΅`` -> ``\\aleph``
802 843
803 844 Used on Python 3 only.
804 845 """
805 846 if len(text)<2:
806 847 return u'', ()
807 848 maybe_slash = text[-2]
808 849 if maybe_slash != '\\':
809 850 return u'', ()
810 851
811 852
812 853 char = text[-1]
813 854 # no expand on quote for completion in strings.
814 855 # nor backcomplete standard ascii keys
815 856 if char in string.ascii_letters or char in ['"',"'"]:
816 857 return u'', ()
817 858 try :
818 859 latex = reverse_latex_symbol[char]
819 860 # '\\' replace the \ as well
820 861 return '\\'+char,[latex]
821 862 except KeyError:
822 863 pass
823 864 return u'', ()
824 865
825 866
826 867 class IPCompleter(Completer):
827 868 """Extension of the completer class with IPython-specific features"""
828 869
829 870 @observe('greedy')
830 871 def _greedy_changed(self, change):
831 872 """update the splitter and readline delims when greedy is changed"""
832 873 if change['new']:
833 874 self.splitter.delims = GREEDY_DELIMS
834 875 else:
835 876 self.splitter.delims = DELIMS
836 877
837 878 merge_completions = Bool(True,
838 879 help="""Whether to merge completion results into a single list
839 880
840 881 If False, only the completion results from the first non-empty
841 882 completer will be returned.
842 883 """
843 884 ).tag(config=True)
844 885 omit__names = Enum((0,1,2), default_value=2,
845 886 help="""Instruct the completer to omit private method names
846 887
847 888 Specifically, when completing on ``object.<tab>``.
848 889
849 890 When 2 [default]: all names that start with '_' will be excluded.
850 891
851 892 When 1: all 'magic' names (``__foo__``) will be excluded.
852 893
853 894 When 0: nothing will be excluded.
854 895 """
855 896 ).tag(config=True)
856 897 limit_to__all__ = Bool(False,
857 898 help="""
858 899 DEPRECATED as of version 5.0.
859 900
860 901 Instruct the completer to use __all__ for the completion
861 902
862 903 Specifically, when completing on ``object.<tab>``.
863 904
864 905 When True: only those names in obj.__all__ will be included.
865 906
866 907 When False [default]: the __all__ attribute is ignored
867 908 """,
868 909 ).tag(config=True)
869 910
870 911 @observe('limit_to__all__')
871 912 def _limit_to_all_changed(self, change):
872 913 warnings.warn('`IPython.core.IPCompleter.limit_to__all__` configuration '
873 914 'value has been deprecated since IPython 5.0, will be made to have '
874 915 'no effects and then removed in future version of IPython.',
875 916 UserWarning)
876 917
877 918 def __init__(self, shell=None, namespace=None, global_namespace=None,
878 919 use_readline=_deprecation_readline_sentinel, config=None, **kwargs):
879 920 """IPCompleter() -> completer
880 921
881 922 Return a completer object.
882 923
883 924 Parameters
884 925 ----------
885 926
886 927 shell
887 928 a pointer to the ipython shell itself. This is needed
888 929 because this completer knows about magic functions, and those can
889 930 only be accessed via the ipython instance.
890 931
891 932 namespace : dict, optional
892 933 an optional dict where completions are performed.
893 934
894 935 global_namespace : dict, optional
895 936 secondary optional dict for completions, to
896 937 handle cases (such as IPython embedded inside functions) where
897 938 both Python scopes are visible.
898 939
899 940 use_readline : bool, optional
900 941 DEPRECATED, ignored since IPython 6.0, will have no effects
901 942 """
902 943
903 944 self.magic_escape = ESC_MAGIC
904 945 self.splitter = CompletionSplitter()
905 946
906 947 if use_readline is not _deprecation_readline_sentinel:
907 948 warnings.warn('The `use_readline` parameter is deprecated and ignored since IPython 6.0.',
908 949 DeprecationWarning, stacklevel=2)
909 950
910 951 # _greedy_changed() depends on splitter and readline being defined:
911 952 Completer.__init__(self, namespace=namespace, global_namespace=global_namespace,
912 953 config=config, **kwargs)
913 954
914 955 # List where completion matches will be stored
915 956 self.matches = []
916 957 self.shell = shell
917 958 # Regexp to split filenames with spaces in them
918 959 self.space_name_re = re.compile(r'([^\\] )')
919 960 # Hold a local ref. to glob.glob for speed
920 961 self.glob = glob.glob
921 962
922 963 # Determine if we are running on 'dumb' terminals, like (X)Emacs
923 964 # buffers, to avoid completion problems.
924 965 term = os.environ.get('TERM','xterm')
925 966 self.dumb_terminal = term in ['dumb','emacs']
926 967
927 968 # Special handling of backslashes needed in win32 platforms
928 969 if sys.platform == "win32":
929 970 self.clean_glob = self._clean_glob_win32
930 971 else:
931 972 self.clean_glob = self._clean_glob
932 973
933 974 #regexp to parse docstring for function signature
934 975 self.docstring_sig_re = re.compile(r'^[\w|\s.]+\(([^)]*)\).*')
935 976 self.docstring_kwd_re = re.compile(r'[\s|\[]*(\w+)(?:\s*=\s*.*)')
936 977 #use this if positional argument name is also needed
937 978 #= re.compile(r'[\s|\[]*(\w+)(?:\s*=?\s*.*)')
938 979
939 980 # All active matcher routines for completion
940 981 self.matchers = [
941 982 self.python_matches,
942 983 self.file_matches,
943 984 self.magic_matches,
944 985 self.python_func_kw_matches,
945 986 self.dict_key_matches,
946 987 ]
947 988
948 989 # This is set externally by InteractiveShell
949 990 self.custom_completers = None
950 991
951 992 def all_completions(self, text):
952 993 """
953 994 Wrapper around the complete method for the benefit of emacs.
954 995 """
955 996 return self.complete(text)[1]
956 997
957 998 def _clean_glob(self, text):
958 999 return self.glob("%s*" % text)
959 1000
960 1001 def _clean_glob_win32(self,text):
961 1002 return [f.replace("\\","/")
962 1003 for f in self.glob("%s*" % text)]
963 1004
964 1005 def file_matches(self, text):
965 1006 """Match filenames, expanding ~USER type strings.
966 1007
967 1008 Most of the seemingly convoluted logic in this completer is an
968 1009 attempt to handle filenames with spaces in them. And yet it's not
969 1010 quite perfect, because Python's readline doesn't expose all of the
970 1011 GNU readline details needed for this to be done correctly.
971 1012
972 1013 For a filename with a space in it, the printed completions will be
973 1014 only the parts after what's already been typed (instead of the
974 1015 full completions, as is normally done). I don't think with the
975 1016 current (as of Python 2.3) Python readline it's possible to do
976 1017 better."""
977 1018
978 1019 # chars that require escaping with backslash - i.e. chars
979 1020 # that readline treats incorrectly as delimiters, but we
980 1021 # don't want to treat as delimiters in filename matching
981 1022 # when escaped with backslash
982 1023 if text.startswith('!'):
983 1024 text = text[1:]
984 1025 text_prefix = u'!'
985 1026 else:
986 1027 text_prefix = u''
987 1028
988 1029 text_until_cursor = self.text_until_cursor
989 1030 # track strings with open quotes
990 1031 open_quotes = has_open_quotes(text_until_cursor)
991 1032
992 1033 if '(' in text_until_cursor or '[' in text_until_cursor:
993 1034 lsplit = text
994 1035 else:
995 1036 try:
996 1037 # arg_split ~ shlex.split, but with unicode bugs fixed by us
997 1038 lsplit = arg_split(text_until_cursor)[-1]
998 1039 except ValueError:
999 1040 # typically an unmatched ", or backslash without escaped char.
1000 1041 if open_quotes:
1001 1042 lsplit = text_until_cursor.split(open_quotes)[-1]
1002 1043 else:
1003 1044 return []
1004 1045 except IndexError:
1005 1046 # tab pressed on empty line
1006 1047 lsplit = ""
1007 1048
1008 1049 if not open_quotes and lsplit != protect_filename(lsplit):
1009 1050 # if protectables are found, do matching on the whole escaped name
1010 1051 has_protectables = True
1011 1052 text0,text = text,lsplit
1012 1053 else:
1013 1054 has_protectables = False
1014 1055 text = os.path.expanduser(text)
1015 1056
1016 1057 if text == "":
1017 1058 return [text_prefix + cast_unicode_py2(protect_filename(f)) for f in self.glob("*")]
1018 1059
1019 1060 # Compute the matches from the filesystem
1020 1061 if sys.platform == 'win32':
1021 1062 m0 = self.clean_glob(text)
1022 1063 else:
1023 1064 m0 = self.clean_glob(text.replace('\\', ''))
1024 1065
1025 1066 if has_protectables:
1026 1067 # If we had protectables, we need to revert our changes to the
1027 1068 # beginning of filename so that we don't double-write the part
1028 1069 # of the filename we have so far
1029 1070 len_lsplit = len(lsplit)
1030 1071 matches = [text_prefix + text0 +
1031 1072 protect_filename(f[len_lsplit:]) for f in m0]
1032 1073 else:
1033 1074 if open_quotes:
1034 1075 # if we have a string with an open quote, we don't need to
1035 1076 # protect the names at all (and we _shouldn't_, as it
1036 1077 # would cause bugs when the filesystem call is made).
1037 1078 matches = m0
1038 1079 else:
1039 1080 matches = [text_prefix +
1040 1081 protect_filename(f) for f in m0]
1041 1082
1042 1083 # Mark directories in input list by appending '/' to their names.
1043 1084 return [cast_unicode_py2(x+'/') if os.path.isdir(x) else x for x in matches]
1044 1085
1045 1086 def magic_matches(self, text):
1046 1087 """Match magics"""
1047 1088 # Get all shell magics now rather than statically, so magics loaded at
1048 1089 # runtime show up too.
1049 1090 lsm = self.shell.magics_manager.lsmagic()
1050 1091 line_magics = lsm['line']
1051 1092 cell_magics = lsm['cell']
1052 1093 pre = self.magic_escape
1053 1094 pre2 = pre+pre
1054 1095
1055 1096 # Completion logic:
1056 1097 # - user gives %%: only do cell magics
1057 1098 # - user gives %: do both line and cell magics
1058 1099 # - no prefix: do both
1059 1100 # In other words, line magics are skipped if the user gives %% explicitly
1060 1101 bare_text = text.lstrip(pre)
1061 1102 comp = [ pre2+m for m in cell_magics if m.startswith(bare_text)]
1062 1103 if not text.startswith(pre2):
1063 1104 comp += [ pre+m for m in line_magics if m.startswith(bare_text)]
1064 1105 return [cast_unicode_py2(c) for c in comp]
1065 1106
1066 1107 def _jedi_matches(self, cursor_column:int, cursor_line:int, text:str):
1067 1108 """
1068 1109
1069 1110 Return a list of :any:`jedi.api.Completions` object from a ``text`` and
1070 1111 cursor position.
1071 1112
1072 1113 Parameters
1073 1114 ----------
1074 1115 cursor_column : int
1075 1116 column position of the cursor in ``text``, 0-indexed.
1076 1117 cursor_line : int
1077 1118 line position of the cursor in ``text``, 0-indexed
1078 1119 text : str
1079 1120 text to complete
1080 1121
1081 1122 Debugging
1082 1123 ---------
1083 1124
1084 1125 If ``IPCompleter.debug`` is ``True`` may return a :any:`_FakeJediCompletion`
1085 1126 object containing a string with the Jedi debug information attached.
1086 1127 """
1087 1128 namespaces = [self.namespace]
1088 1129 if self.global_namespace is not None:
1089 1130 namespaces.append(self.global_namespace)
1090 1131
1091 1132 # cursor_pos is an it, jedi wants line and column
1092 1133 offset = cursor_to_position(text, cursor_line, cursor_column)
1093 1134 if offset:
1094 1135 pre = text[offset-1]
1095 1136 completion_filter = lambda x:x
1096 1137 if pre == '.':
1097 1138 if self.omit__names == 2:
1098 1139 completion_filter = lambda c:not c.name.startswith('_')
1099 1140 elif self.omit__names == 1:
1100 1141 completion_filter = lambda c:not (c.name.startswith('__') and c.name.endswith('__'))
1101 1142 elif self.omit__names == 0:
1102 1143 completion_filter = lambda x:x
1103 1144 else:
1104 1145 raise ValueError("Don't understand self.omit__names == {}".format(self.omit__names))
1105 1146
1106 1147 interpreter = jedi.Interpreter(
1107 1148 text, namespaces, column=cursor_column, line=cursor_line + 1)
1108 1149 try:
1109 1150 return filter(completion_filter, interpreter.completions())
1110 1151 except Exception as e:
1111 1152 if self.debug:
1112 1153 return [_FakeJediCompletion('Opps Jedi has crash please report a bug with the following:\n"""\n%s\ns"""' % (e))]
1113 1154 else:
1114 1155 return []
1115 1156
1116 1157 def python_matches(self, text):
1117 1158 """Match attributes or global python names"""
1118 1159 if "." in text:
1119 1160 try:
1120 1161 matches = self.attr_matches(text)
1121 1162 if text.endswith('.') and self.omit__names:
1122 1163 if self.omit__names == 1:
1123 1164 # true if txt is _not_ a __ name, false otherwise:
1124 1165 no__name = (lambda txt:
1125 1166 re.match(r'.*\.__.*?__',txt) is None)
1126 1167 else:
1127 1168 # true if txt is _not_ a _ name, false otherwise:
1128 1169 no__name = (lambda txt:
1129 1170 re.match(r'\._.*?',txt[txt.rindex('.'):]) is None)
1130 1171 matches = filter(no__name, matches)
1131 1172 except NameError:
1132 1173 # catches <undefined attributes>.<tab>
1133 1174 matches = []
1134 1175 else:
1135 1176 matches = self.global_matches(text)
1136 1177 return matches
1137 1178
1138 1179 def _default_arguments_from_docstring(self, doc):
1139 1180 """Parse the first line of docstring for call signature.
1140 1181
1141 1182 Docstring should be of the form 'min(iterable[, key=func])\n'.
1142 1183 It can also parse cython docstring of the form
1143 1184 'Minuit.migrad(self, int ncall=10000, resume=True, int nsplit=1)'.
1144 1185 """
1145 1186 if doc is None:
1146 1187 return []
1147 1188
1148 1189 #care only the firstline
1149 1190 line = doc.lstrip().splitlines()[0]
1150 1191
1151 1192 #p = re.compile(r'^[\w|\s.]+\(([^)]*)\).*')
1152 1193 #'min(iterable[, key=func])\n' -> 'iterable[, key=func]'
1153 1194 sig = self.docstring_sig_re.search(line)
1154 1195 if sig is None:
1155 1196 return []
1156 1197 # iterable[, key=func]' -> ['iterable[' ,' key=func]']
1157 1198 sig = sig.groups()[0].split(',')
1158 1199 ret = []
1159 1200 for s in sig:
1160 1201 #re.compile(r'[\s|\[]*(\w+)(?:\s*=\s*.*)')
1161 1202 ret += self.docstring_kwd_re.findall(s)
1162 1203 return ret
1163 1204
1164 1205 def _default_arguments(self, obj):
1165 1206 """Return the list of default arguments of obj if it is callable,
1166 1207 or empty list otherwise."""
1167 1208 call_obj = obj
1168 1209 ret = []
1169 1210 if inspect.isbuiltin(obj):
1170 1211 pass
1171 1212 elif not (inspect.isfunction(obj) or inspect.ismethod(obj)):
1172 1213 if inspect.isclass(obj):
1173 1214 #for cython embededsignature=True the constructor docstring
1174 1215 #belongs to the object itself not __init__
1175 1216 ret += self._default_arguments_from_docstring(
1176 1217 getattr(obj, '__doc__', ''))
1177 1218 # for classes, check for __init__,__new__
1178 1219 call_obj = (getattr(obj, '__init__', None) or
1179 1220 getattr(obj, '__new__', None))
1180 1221 # for all others, check if they are __call__able
1181 1222 elif hasattr(obj, '__call__'):
1182 1223 call_obj = obj.__call__
1183 1224 ret += self._default_arguments_from_docstring(
1184 1225 getattr(call_obj, '__doc__', ''))
1185 1226
1186 1227 _keeps = (inspect.Parameter.KEYWORD_ONLY,
1187 1228 inspect.Parameter.POSITIONAL_OR_KEYWORD)
1188 1229
1189 1230 try:
1190 1231 sig = inspect.signature(call_obj)
1191 1232 ret.extend(k for k, v in sig.parameters.items() if
1192 1233 v.kind in _keeps)
1193 1234 except ValueError:
1194 1235 pass
1195 1236
1196 1237 return list(set(ret))
1197 1238
1198 1239 def python_func_kw_matches(self,text):
1199 1240 """Match named parameters (kwargs) of the last open function"""
1200 1241
1201 1242 if "." in text: # a parameter cannot be dotted
1202 1243 return []
1203 1244 try: regexp = self.__funcParamsRegex
1204 1245 except AttributeError:
1205 1246 regexp = self.__funcParamsRegex = re.compile(r'''
1206 1247 '.*?(?<!\\)' | # single quoted strings or
1207 1248 ".*?(?<!\\)" | # double quoted strings or
1208 1249 \w+ | # identifier
1209 1250 \S # other characters
1210 1251 ''', re.VERBOSE | re.DOTALL)
1211 1252 # 1. find the nearest identifier that comes before an unclosed
1212 1253 # parenthesis before the cursor
1213 1254 # e.g. for "foo (1+bar(x), pa<cursor>,a=1)", the candidate is "foo"
1214 1255 tokens = regexp.findall(self.text_until_cursor)
1215 1256 iterTokens = reversed(tokens); openPar = 0
1216 1257
1217 1258 for token in iterTokens:
1218 1259 if token == ')':
1219 1260 openPar -= 1
1220 1261 elif token == '(':
1221 1262 openPar += 1
1222 1263 if openPar > 0:
1223 1264 # found the last unclosed parenthesis
1224 1265 break
1225 1266 else:
1226 1267 return []
1227 1268 # 2. Concatenate dotted names ("foo.bar" for "foo.bar(x, pa" )
1228 1269 ids = []
1229 1270 isId = re.compile(r'\w+$').match
1230 1271
1231 1272 while True:
1232 1273 try:
1233 1274 ids.append(next(iterTokens))
1234 1275 if not isId(ids[-1]):
1235 1276 ids.pop(); break
1236 1277 if not next(iterTokens) == '.':
1237 1278 break
1238 1279 except StopIteration:
1239 1280 break
1240 1281
1241 1282 # Find all named arguments already assigned to, as to avoid suggesting
1242 1283 # them again
1243 1284 usedNamedArgs = set()
1244 1285 par_level = -1
1245 1286 for token, next_token in zip(tokens, tokens[1:]):
1246 1287 if token == '(':
1247 1288 par_level += 1
1248 1289 elif token == ')':
1249 1290 par_level -= 1
1250 1291
1251 1292 if par_level != 0:
1252 1293 continue
1253 1294
1254 1295 if next_token != '=':
1255 1296 continue
1256 1297
1257 1298 usedNamedArgs.add(token)
1258 1299
1259 1300 # lookup the candidate callable matches either using global_matches
1260 1301 # or attr_matches for dotted names
1261 1302 if len(ids) == 1:
1262 1303 callableMatches = self.global_matches(ids[0])
1263 1304 else:
1264 1305 callableMatches = self.attr_matches('.'.join(ids[::-1]))
1265 1306 argMatches = []
1266 1307 for callableMatch in callableMatches:
1267 1308 try:
1268 1309 namedArgs = self._default_arguments(eval(callableMatch,
1269 1310 self.namespace))
1270 1311 except:
1271 1312 continue
1272 1313
1273 1314 # Remove used named arguments from the list, no need to show twice
1274 1315 for namedArg in set(namedArgs) - usedNamedArgs:
1275 1316 if namedArg.startswith(text):
1276 1317 argMatches.append(u"%s=" %namedArg)
1277 1318 return argMatches
1278 1319
1279 1320 def dict_key_matches(self, text):
1280 1321 "Match string keys in a dictionary, after e.g. 'foo[' "
1281 1322 def get_keys(obj):
1282 1323 # Objects can define their own completions by defining an
1283 1324 # _ipy_key_completions_() method.
1284 1325 method = get_real_method(obj, '_ipython_key_completions_')
1285 1326 if method is not None:
1286 1327 return method()
1287 1328
1288 1329 # Special case some common in-memory dict-like types
1289 1330 if isinstance(obj, dict) or\
1290 1331 _safe_isinstance(obj, 'pandas', 'DataFrame'):
1291 1332 try:
1292 1333 return list(obj.keys())
1293 1334 except Exception:
1294 1335 return []
1295 1336 elif _safe_isinstance(obj, 'numpy', 'ndarray') or\
1296 1337 _safe_isinstance(obj, 'numpy', 'void'):
1297 1338 return obj.dtype.names or []
1298 1339 return []
1299 1340
1300 1341 try:
1301 1342 regexps = self.__dict_key_regexps
1302 1343 except AttributeError:
1303 1344 dict_key_re_fmt = r'''(?x)
1304 1345 ( # match dict-referring expression wrt greedy setting
1305 1346 %s
1306 1347 )
1307 1348 \[ # open bracket
1308 1349 \s* # and optional whitespace
1309 1350 ([uUbB]? # string prefix (r not handled)
1310 1351 (?: # unclosed string
1311 1352 '(?:[^']|(?<!\\)\\')*
1312 1353 |
1313 1354 "(?:[^"]|(?<!\\)\\")*
1314 1355 )
1315 1356 )?
1316 1357 $
1317 1358 '''
1318 1359 regexps = self.__dict_key_regexps = {
1319 1360 False: re.compile(dict_key_re_fmt % '''
1320 1361 # identifiers separated by .
1321 1362 (?!\d)\w+
1322 1363 (?:\.(?!\d)\w+)*
1323 1364 '''),
1324 1365 True: re.compile(dict_key_re_fmt % '''
1325 1366 .+
1326 1367 ''')
1327 1368 }
1328 1369
1329 1370 match = regexps[self.greedy].search(self.text_until_cursor)
1330 1371 if match is None:
1331 1372 return []
1332 1373
1333 1374 expr, prefix = match.groups()
1334 1375 try:
1335 1376 obj = eval(expr, self.namespace)
1336 1377 except Exception:
1337 1378 try:
1338 1379 obj = eval(expr, self.global_namespace)
1339 1380 except Exception:
1340 1381 return []
1341 1382
1342 1383 keys = get_keys(obj)
1343 1384 if not keys:
1344 1385 return keys
1345 1386 closing_quote, token_offset, matches = match_dict_keys(keys, prefix, self.splitter.delims)
1346 1387 if not matches:
1347 1388 return matches
1348 1389
1349 1390 # get the cursor position of
1350 1391 # - the text being completed
1351 1392 # - the start of the key text
1352 1393 # - the start of the completion
1353 1394 text_start = len(self.text_until_cursor) - len(text)
1354 1395 if prefix:
1355 1396 key_start = match.start(2)
1356 1397 completion_start = key_start + token_offset
1357 1398 else:
1358 1399 key_start = completion_start = match.end()
1359 1400
1360 1401 # grab the leading prefix, to make sure all completions start with `text`
1361 1402 if text_start > key_start:
1362 1403 leading = ''
1363 1404 else:
1364 1405 leading = text[text_start:completion_start]
1365 1406
1366 1407 # the index of the `[` character
1367 1408 bracket_idx = match.end(1)
1368 1409
1369 1410 # append closing quote and bracket as appropriate
1370 1411 # this is *not* appropriate if the opening quote or bracket is outside
1371 1412 # the text given to this method
1372 1413 suf = ''
1373 1414 continuation = self.line_buffer[len(self.text_until_cursor):]
1374 1415 if key_start > text_start and closing_quote:
1375 1416 # quotes were opened inside text, maybe close them
1376 1417 if continuation.startswith(closing_quote):
1377 1418 continuation = continuation[len(closing_quote):]
1378 1419 else:
1379 1420 suf += closing_quote
1380 1421 if bracket_idx > text_start:
1381 1422 # brackets were opened inside text, maybe close them
1382 1423 if not continuation.startswith(']'):
1383 1424 suf += ']'
1384 1425
1385 1426 return [leading + k + suf for k in matches]
1386 1427
1387 1428 def unicode_name_matches(self, text):
1388 1429 u"""Match Latex-like syntax for unicode characters base
1389 1430 on the name of the character.
1390 1431
1391 1432 This does ``\\GREEK SMALL LETTER ETA`` -> ``Ξ·``
1392 1433
1393 1434 Works only on valid python 3 identifier, or on combining characters that
1394 1435 will combine to form a valid identifier.
1395 1436
1396 1437 Used on Python 3 only.
1397 1438 """
1398 1439 slashpos = text.rfind('\\')
1399 1440 if slashpos > -1:
1400 1441 s = text[slashpos+1:]
1401 1442 try :
1402 1443 unic = unicodedata.lookup(s)
1403 1444 # allow combining chars
1404 1445 if ('a'+unic).isidentifier():
1405 1446 return '\\'+s,[unic]
1406 1447 except KeyError:
1407 1448 pass
1408 1449 return u'', []
1409 1450
1410 1451
1411 1452 def latex_matches(self, text):
1412 1453 u"""Match Latex syntax for unicode characters.
1413 1454
1414 1455 This does both ``\\alp`` -> ``\\alpha`` and ``\\alpha`` -> ``Ξ±``
1415 1456
1416 1457 Used on Python 3 only.
1417 1458 """
1418 1459 slashpos = text.rfind('\\')
1419 1460 if slashpos > -1:
1420 1461 s = text[slashpos:]
1421 1462 if s in latex_symbols:
1422 1463 # Try to complete a full latex symbol to unicode
1423 1464 # \\alpha -> Ξ±
1424 1465 return s, [latex_symbols[s]]
1425 1466 else:
1426 1467 # If a user has partially typed a latex symbol, give them
1427 1468 # a full list of options \al -> [\aleph, \alpha]
1428 1469 matches = [k for k in latex_symbols if k.startswith(s)]
1429 1470 return s, matches
1430 1471 return u'', []
1431 1472
1432 1473 def dispatch_custom_completer(self, text):
1433 1474 if not self.custom_completers:
1434 1475 return
1435 1476
1436 1477 line = self.line_buffer
1437 1478 if not line.strip():
1438 1479 return None
1439 1480
1440 1481 # Create a little structure to pass all the relevant information about
1441 1482 # the current completion to any custom completer.
1442 1483 event = SimpleNamespace()
1443 1484 event.line = line
1444 1485 event.symbol = text
1445 1486 cmd = line.split(None,1)[0]
1446 1487 event.command = cmd
1447 1488 event.text_until_cursor = self.text_until_cursor
1448 1489
1449 1490 # for foo etc, try also to find completer for %foo
1450 1491 if not cmd.startswith(self.magic_escape):
1451 1492 try_magic = self.custom_completers.s_matches(
1452 1493 self.magic_escape + cmd)
1453 1494 else:
1454 1495 try_magic = []
1455 1496
1456 1497 for c in itertools.chain(self.custom_completers.s_matches(cmd),
1457 1498 try_magic,
1458 1499 self.custom_completers.flat_matches(self.text_until_cursor)):
1459 1500 try:
1460 1501 res = c(event)
1461 1502 if res:
1462 1503 # first, try case sensitive match
1463 1504 withcase = [cast_unicode_py2(r) for r in res if r.startswith(text)]
1464 1505 if withcase:
1465 1506 return withcase
1466 1507 # if none, then case insensitive ones are ok too
1467 1508 text_low = text.lower()
1468 1509 return [cast_unicode_py2(r) for r in res if r.lower().startswith(text_low)]
1469 1510 except TryNext:
1470 1511 pass
1471 1512
1472 1513 return None
1473 1514
1474 1515 def completions(self, text: str, offset: int)->Iterator[Completion]:
1475 1516 """
1476 1517 Returns an iterator over the possible completions
1477 1518
1478 1519 .. warning:: Unstable
1479 1520
1480 1521 This function is unstable, API may change without warning.
1481 1522 It will also raise unless use in proper context manager.
1482 1523
1483 1524 Parameters
1484 1525 ----------
1485 1526
1486 1527 text:str
1487 1528 Full text of the current input, multi line string.
1488 1529 offset:int
1489 1530 Integer representing the position of the cursor in ``text``. Offset
1490 1531 is 0-based indexed.
1491 1532
1492 1533 Yields
1493 1534 ------
1494 1535 :any:`Completion` object
1495 1536
1496 1537
1497 1538 The cursor on a text can either be seen as being "in between"
1498 1539 characters or "On" a character depending on the interface visible to
1499 1540 the user. For consistency the cursor being on "in between" characters X
1500 1541 and Y is equivalent to the cursor being "on" character Y, that is to say
1501 1542 the character the cursor is on is considered as being after the cursor.
1502 1543
1503 1544 Combining characters may span more that one position in the
1504 1545 text.
1505 1546
1506 1547
1507 1548 .. note::
1508 1549
1509 1550 If ``IPCompleter.debug`` is :any:`True` will yield a ``--jedi/ipython--``
1510 1551 fake Completion token to distinguish completion returned by Jedi
1511 1552 and usual IPython completion.
1512 1553
1554 .. note::
1555
1556 Completions are not completely deduplicated yet. If identical
1557 completions are coming from different sources this function does not
1558 ensure that each completion object will only be present once.
1513 1559 """
1514 1560 warnings.warn("_complete is a provisional API (as of IPython 6.0). "
1515 1561 "It may change without warnings. "
1516 1562 "Use in corresponding context manager.",
1517 1563 category=ProvisionalCompleterWarning, stacklevel=2)
1518 1564
1519 # Possible Improvements / Known limitation
1520 ##########################################
1521 # Completions may be identical even if they have different ranges and
1522 # text. For example:
1523 # >>> a=1
1524 # >>> a.<tab>
1525 # May returns:
1526 # - `a.real` from 0 to 2
1527 # - `.real` from 1 to 2
1528 # the current code does not (yet) check for such equivalence
1529 1565 seen = set()
1530 1566 for c in self._completions(text, offset, _timeout=self.jedi_compute_type_timeout/1000):
1531 1567 if c and (c in seen):
1532 1568 continue
1533 1569 yield c
1534 1570 seen.add(c)
1535 1571
1536 1572 def _completions(self, full_text: str, offset: int, *, _timeout)->Iterator[Completion]:
1537 1573 """
1538 1574 Core completion module.Same signature as :any:`completions`, with the
1539 1575 extra `timeout` parameter (in seconds).
1540 1576
1541 1577
1542 1578 Computing jedi's completion ``.type`` can be quite expensive (it is a
1543 1579 lazy property) and can require some warm-up, more warm up than just
1544 1580 computing the ``name`` of a completion. The warm-up can be :
1545 1581
1546 1582 - Long warm-up the fisrt time a module is encountered after
1547 1583 install/update: actually build parse/inference tree.
1548 1584
1549 1585 - first time the module is encountered in a session: load tree from
1550 1586 disk.
1551 1587
1552 1588 We don't want to block completions for tens of seconds so we give the
1553 1589 completer a "budget" of ``_timeout`` seconds per invocation to compute
1554 1590 completions types, the completions that have not yet been computed will
1555 1591 be marked as "unknown" an will have a chance to be computed next round
1556 1592 are things get cached.
1557 1593
1558 1594 Keep in mind that Jedi is not the only thing treating the completion so
1559 1595 keep the timeout short-ish as if we take more than 0.3 second we still
1560 1596 have lots of processing to do.
1561 1597
1562 1598 """
1563 1599 deadline = time.monotonic() + _timeout
1564 1600
1565 1601
1566 1602 before = full_text[:offset]
1567 1603 cursor_line, cursor_column = position_to_cursor(full_text, offset)
1568 1604
1569 1605 matched_text, matches, matches_origin, jedi_matches = self._complete(
1570 1606 full_text=full_text, cursor_line=cursor_line, cursor_pos=cursor_column)
1571 1607
1572 1608 iter_jm = iter(jedi_matches)
1573 1609 if _timeout:
1574 1610 for jm in iter_jm:
1575 1611 try:
1576 1612 type_ = jm.type
1577 1613 except Exception:
1578 1614 if self.debug:
1579 1615 print("Error in Jedi getting type of ", jm)
1580 1616 type_ = None
1581 1617 delta = len(jm.name_with_symbols) - len(jm.complete)
1582 1618 yield Completion(start=offset - delta,
1583 1619 end=offset,
1584 1620 text=jm.name_with_symbols,
1585 1621 type=type_,
1586 1622 _origin='jedi')
1587 1623
1588 1624 if time.monotonic() > deadline:
1589 1625 break
1590 1626
1591 1627 for jm in iter_jm:
1592 1628 delta = len(jm.name_with_symbols) - len(jm.complete)
1593 1629 yield Completion(start=offset - delta,
1594 1630 end=offset,
1595 1631 text=jm.name_with_symbols,
1596 1632 type='<unknown>', # don't compute type for speed
1597 1633 _origin='jedi')
1598 1634
1599 1635
1600 1636 start_offset = before.rfind(matched_text)
1601 1637
1602 1638 # TODO:
1603 1639 # Supress this, right now just for debug.
1604 1640 if jedi_matches and matches and self.debug:
1605 1641 yield Completion(start=start_offset, end=offset, text='--jedi/ipython--', _origin='debug')
1606 1642
1607 1643 # I'm unsure if this is always true, so let's assert and see if it
1608 1644 # crash
1609 1645 assert before.endswith(matched_text)
1610 1646 for m, t in zip(matches, matches_origin):
1611 1647 yield Completion(start=start_offset, end=offset, text=m, _origin=t)
1612 1648
1613 1649
1614 1650 def complete(self, text=None, line_buffer=None, cursor_pos=None):
1615 1651 """Find completions for the given text and line context.
1616 1652
1617 1653 Note that both the text and the line_buffer are optional, but at least
1618 1654 one of them must be given.
1619 1655
1620 1656 Parameters
1621 1657 ----------
1622 1658 text : string, optional
1623 1659 Text to perform the completion on. If not given, the line buffer
1624 1660 is split using the instance's CompletionSplitter object.
1625 1661
1626 1662 line_buffer : string, optional
1627 1663 If not given, the completer attempts to obtain the current line
1628 1664 buffer via readline. This keyword allows clients which are
1629 1665 requesting for text completions in non-readline contexts to inform
1630 1666 the completer of the entire text.
1631 1667
1632 1668 cursor_pos : int, optional
1633 1669 Index of the cursor in the full line buffer. Should be provided by
1634 1670 remote frontends where kernel has no access to frontend state.
1635 1671
1636 1672 Returns
1637 1673 -------
1638 1674 text : str
1639 1675 Text that was actually used in the completion.
1640 1676
1641 1677 matches : list
1642 1678 A list of completion matches.
1643 1679
1644 1680
1645 1681 .. note::
1646 1682
1647 1683 This API is likely to be deprecated and replaced by
1648 1684 :any:`IPCompleter.completions` in the future.
1649 1685
1650 1686
1651 1687 """
1652 1688 warnings.warn('`Completer.complete` is pending deprecation since '
1653 1689 'IPython 6.0 and will be replaced by `Completer.completions`.',
1654 1690 PendingDeprecationWarning)
1655 1691 # potential todo, FOLD the 3rd throw away argument of _complete
1656 1692 # into the first 2 one.
1657 1693 return self._complete(line_buffer=line_buffer, cursor_pos=cursor_pos, text=text, cursor_line=0)[:2]
1658 1694
1659 1695 def _complete(self, *, cursor_line, cursor_pos, line_buffer=None, text=None,
1660 1696 full_text=None, return_jedi_results=True) -> (str, List[str], List[object]):
1661 1697 """
1662 1698
1663 1699 Like complete but can also returns raw jedi completions as well as the
1664 1700 origin of the completion text. This could (and should) be made much
1665 1701 cleaner but that will be simpler once we drop the old (and stateful)
1666 1702 :any:`complete` API.
1667 1703
1668 1704
1669 1705 With current provisional API, cursor_pos act both (depending on the
1670 1706 caller) as the offset in the ``text`` or ``line_buffer``, or as the
1671 1707 ``column`` when passing multiline strings this could/should be renamed
1672 1708 but would add extra noise.
1673 1709 """
1674 1710
1675 1711 # if the cursor position isn't given, the only sane assumption we can
1676 1712 # make is that it's at the end of the line (the common case)
1677 1713 if cursor_pos is None:
1678 1714 cursor_pos = len(line_buffer) if text is None else len(text)
1679 1715
1680 1716 if self.use_main_ns:
1681 1717 self.namespace = __main__.__dict__
1682 1718
1683 1719 # if text is either None or an empty string, rely on the line buffer
1684 1720 if (not line_buffer) and full_text:
1685 1721 line_buffer = full_text.split('\n')[cursor_line]
1686 1722 if not text:
1687 1723 text = self.splitter.split_line(line_buffer, cursor_pos)
1688 1724
1689 1725 base_text = text if not line_buffer else line_buffer[:cursor_pos]
1690 1726 latex_text, latex_matches = self.latex_matches(base_text)
1691 1727 if latex_matches:
1692 1728 return latex_text, latex_matches, ['latex_matches']*len(latex_matches), ()
1693 1729 name_text = ''
1694 1730 name_matches = []
1695 1731 for meth in (self.unicode_name_matches, back_latex_name_matches, back_unicode_name_matches):
1696 1732 name_text, name_matches = meth(base_text)
1697 1733 if name_text:
1698 1734 return name_text, name_matches, [meth.__qualname__]*len(name_matches), {}
1699 1735
1700 1736
1701 1737 # If no line buffer is given, assume the input text is all there was
1702 1738 if line_buffer is None:
1703 1739 line_buffer = text
1704 1740
1705 1741 self.line_buffer = line_buffer
1706 1742 self.text_until_cursor = self.line_buffer[:cursor_pos]
1707 1743
1708 1744 # Start with a clean slate of completions
1709 1745 matches = []
1710 1746 custom_res = self.dispatch_custom_completer(text)
1711 1747 # FIXME: we should extend our api to return a dict with completions for
1712 1748 # different types of objects. The rlcomplete() method could then
1713 1749 # simply collapse the dict into a list for readline, but we'd have
1714 1750 # richer completion semantics in other evironments.
1715 1751 completions = ()
1716 1752 if self.use_jedi and return_jedi_results:
1717 1753 if not full_text:
1718 1754 full_text = line_buffer
1719 1755 completions = self._jedi_matches(
1720 1756 cursor_pos, cursor_line, full_text)
1721 1757 if custom_res is not None:
1722 1758 # did custom completers produce something?
1723 1759 matches = [(m, 'custom') for m in custom_res]
1724 1760 else:
1725 1761 # Extend the list of completions with the results of each
1726 1762 # matcher, so we return results to the user from all
1727 1763 # namespaces.
1728 1764 if self.merge_completions:
1729 1765 matches = []
1730 1766 for matcher in self.matchers:
1731 1767 try:
1732 1768 matches.extend([(m, matcher.__qualname__)
1733 1769 for m in matcher(text)])
1734 1770 except:
1735 1771 # Show the ugly traceback if the matcher causes an
1736 1772 # exception, but do NOT crash the kernel!
1737 1773 sys.excepthook(*sys.exc_info())
1738 1774 else:
1739 1775 for matcher in self.matchers:
1740 1776 matches = [(m, matcher.__qualname__)
1741 1777 for m in matcher(text)]
1742 1778 if matches:
1743 1779 break
1744 1780 seen = set()
1745 1781 filtered_matches = set()
1746 1782 for m in matches:
1747 1783 t, c = m
1748 1784 if t not in seen:
1749 1785 filtered_matches.add(m)
1750 1786 seen.add(t)
1751 1787
1752 1788 filtered_matches = sorted(
1753 1789 set(filtered_matches), key=lambda x: completions_sorting_key(x[0]))
1754 1790
1755 1791 matches = [m[0] for m in filtered_matches]
1756 1792 origins = [m[1] for m in filtered_matches]
1757 1793
1758 1794 self.matches = matches
1759 1795
1760 1796 return text, matches, origins, completions
@@ -1,843 +1,860 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 import textwrap
9 10 import unittest
10 11
11 12 from contextlib import contextmanager
12 13
13 14 import nose.tools as nt
14 15
15 16 from traitlets.config.loader import Config
16 17 from IPython import get_ipython
17 18 from IPython.core import completer
18 19 from IPython.external.decorators import knownfailureif
19 20 from IPython.utils.tempdir import TemporaryDirectory, TemporaryWorkingDirectory
20 21 from IPython.utils.generics import complete_object
21 22 from IPython.testing import decorators as dec
22 23
23 from IPython.core.completer import Completion, provisionalcompleter, match_dict_keys
24 from IPython.core.completer import (
25 Completion, provisionalcompleter, match_dict_keys, _deduplicate_completions)
24 26 from nose.tools import assert_in, assert_not_in
25 27
26 28 #-----------------------------------------------------------------------------
27 29 # Test functions
28 30 #-----------------------------------------------------------------------------
29 31
30 32 @contextmanager
31 33 def greedy_completion():
32 34 ip = get_ipython()
33 35 greedy_original = ip.Completer.greedy
34 36 try:
35 37 ip.Completer.greedy = True
36 38 yield
37 39 finally:
38 40 ip.Completer.greedy = greedy_original
39 41
40 42 def test_protect_filename():
41 43 if sys.platform == 'win32':
42 44 pairs = [('abc','abc'),
43 45 (' abc','" abc"'),
44 46 ('a bc','"a bc"'),
45 47 ('a bc','"a bc"'),
46 48 (' bc','" bc"'),
47 49 ]
48 50 else:
49 51 pairs = [('abc','abc'),
50 52 (' abc',r'\ abc'),
51 53 ('a bc',r'a\ bc'),
52 54 ('a bc',r'a\ \ bc'),
53 55 (' bc',r'\ \ bc'),
54 56 # On posix, we also protect parens and other special characters.
55 57 ('a(bc',r'a\(bc'),
56 58 ('a)bc',r'a\)bc'),
57 59 ('a( )bc',r'a\(\ \)bc'),
58 60 ('a[1]bc', r'a\[1\]bc'),
59 61 ('a{1}bc', r'a\{1\}bc'),
60 62 ('a#bc', r'a\#bc'),
61 63 ('a?bc', r'a\?bc'),
62 64 ('a=bc', r'a\=bc'),
63 65 ('a\\bc', r'a\\bc'),
64 66 ('a|bc', r'a\|bc'),
65 67 ('a;bc', r'a\;bc'),
66 68 ('a:bc', r'a\:bc'),
67 69 ("a'bc", r"a\'bc"),
68 70 ('a*bc', r'a\*bc'),
69 71 ('a"bc', r'a\"bc'),
70 72 ('a^bc', r'a\^bc'),
71 73 ('a&bc', r'a\&bc'),
72 74 ]
73 75 # run the actual tests
74 76 for s1, s2 in pairs:
75 77 s1p = completer.protect_filename(s1)
76 78 nt.assert_equal(s1p, s2)
77 79
78 80
79 81 def check_line_split(splitter, test_specs):
80 82 for part1, part2, split in test_specs:
81 83 cursor_pos = len(part1)
82 84 line = part1+part2
83 85 out = splitter.split_line(line, cursor_pos)
84 86 nt.assert_equal(out, split)
85 87
86 88
87 89 def test_line_split():
88 90 """Basic line splitter test with default specs."""
89 91 sp = completer.CompletionSplitter()
90 92 # The format of the test specs is: part1, part2, expected answer. Parts 1
91 93 # and 2 are joined into the 'line' sent to the splitter, as if the cursor
92 94 # was at the end of part1. So an empty part2 represents someone hitting
93 95 # tab at the end of the line, the most common case.
94 96 t = [('run some/scrip', '', 'some/scrip'),
95 97 ('run scripts/er', 'ror.py foo', 'scripts/er'),
96 98 ('echo $HOM', '', 'HOM'),
97 99 ('print sys.pa', '', 'sys.pa'),
98 100 ('print(sys.pa', '', 'sys.pa'),
99 101 ("execfile('scripts/er", '', 'scripts/er'),
100 102 ('a[x.', '', 'x.'),
101 103 ('a[x.', 'y', 'x.'),
102 104 ('cd "some_file/', '', 'some_file/'),
103 105 ]
104 106 check_line_split(sp, t)
105 107 # Ensure splitting works OK with unicode by re-running the tests with
106 108 # all inputs turned into unicode
107 109 check_line_split(sp, [ map(str, p) for p in t] )
108 110
109 111
110 112 def test_custom_completion_error():
111 113 """Test that errors from custom attribute completers are silenced."""
112 114 ip = get_ipython()
113 115 class A(object): pass
114 116 ip.user_ns['a'] = A()
115 117
116 118 @complete_object.when_type(A)
117 119 def complete_A(a, existing_completions):
118 120 raise TypeError("this should be silenced")
119 121
120 122 ip.complete("a.")
121 123
122 124
123 125 def test_unicode_completions():
124 126 ip = get_ipython()
125 127 # Some strings that trigger different types of completion. Check them both
126 128 # in str and unicode forms
127 129 s = ['ru', '%ru', 'cd /', 'floa', 'float(x)/']
128 130 for t in s + list(map(str, s)):
129 131 # We don't need to check exact completion values (they may change
130 132 # depending on the state of the namespace, but at least no exceptions
131 133 # should be thrown and the return value should be a pair of text, list
132 134 # values.
133 135 text, matches = ip.complete(t)
134 136 nt.assert_true(isinstance(text, str))
135 137 nt.assert_true(isinstance(matches, list))
136 138
137 139 def test_latex_completions():
138 140 from IPython.core.latex_symbols import latex_symbols
139 141 import random
140 142 ip = get_ipython()
141 143 # Test some random unicode symbols
142 144 keys = random.sample(latex_symbols.keys(), 10)
143 145 for k in keys:
144 146 text, matches = ip.complete(k)
145 147 nt.assert_equal(len(matches),1)
146 148 nt.assert_equal(text, k)
147 149 nt.assert_equal(matches[0], latex_symbols[k])
148 150 # Test a more complex line
149 151 text, matches = ip.complete(u'print(\\alpha')
150 152 nt.assert_equal(text, u'\\alpha')
151 153 nt.assert_equal(matches[0], latex_symbols['\\alpha'])
152 154 # Test multiple matching latex symbols
153 155 text, matches = ip.complete(u'\\al')
154 156 nt.assert_in('\\alpha', matches)
155 157 nt.assert_in('\\aleph', matches)
156 158
157 159
158 160
159 161
160 162 def test_back_latex_completion():
161 163 ip = get_ipython()
162 164
163 165 # do not return more than 1 matches fro \beta, only the latex one.
164 166 name, matches = ip.complete('\\Ξ²')
165 167 nt.assert_equal(len(matches), 1)
166 168 nt.assert_equal(matches[0], '\\beta')
167 169
168 170 def test_back_unicode_completion():
169 171 ip = get_ipython()
170 172
171 173 name, matches = ip.complete('\\β…€')
172 174 nt.assert_equal(len(matches), 1)
173 175 nt.assert_equal(matches[0], '\\ROMAN NUMERAL FIVE')
174 176
175 177
176 178 def test_forward_unicode_completion():
177 179 ip = get_ipython()
178 180
179 181 name, matches = ip.complete('\\ROMAN NUMERAL FIVE')
180 182 nt.assert_equal(len(matches), 1)
181 183 nt.assert_equal(matches[0], 'β…€')
182 184
183 185 @dec.knownfailureif(sys.platform == 'win32', 'Fails if there is a C:\\j... path')
184 186 def test_no_ascii_back_completion():
185 187 ip = get_ipython()
186 188 with TemporaryWorkingDirectory(): # Avoid any filename completions
187 189 # single ascii letter that don't have yet completions
188 190 for letter in 'jJ' :
189 191 name, matches = ip.complete('\\'+letter)
190 192 nt.assert_equal(matches, [])
191 193
192 194
193 195
194 196
195 197 class CompletionSplitterTestCase(unittest.TestCase):
196 198 def setUp(self):
197 199 self.sp = completer.CompletionSplitter()
198 200
199 201 def test_delim_setting(self):
200 202 self.sp.delims = ' '
201 203 nt.assert_equal(self.sp.delims, ' ')
202 204 nt.assert_equal(self.sp._delim_expr, '[\ ]')
203 205
204 206 def test_spaces(self):
205 207 """Test with only spaces as split chars."""
206 208 self.sp.delims = ' '
207 209 t = [('foo', '', 'foo'),
208 210 ('run foo', '', 'foo'),
209 211 ('run foo', 'bar', 'foo'),
210 212 ]
211 213 check_line_split(self.sp, t)
212 214
213 215
214 216 def test_has_open_quotes1():
215 217 for s in ["'", "'''", "'hi' '"]:
216 218 nt.assert_equal(completer.has_open_quotes(s), "'")
217 219
218 220
219 221 def test_has_open_quotes2():
220 222 for s in ['"', '"""', '"hi" "']:
221 223 nt.assert_equal(completer.has_open_quotes(s), '"')
222 224
223 225
224 226 def test_has_open_quotes3():
225 227 for s in ["''", "''' '''", "'hi' 'ipython'"]:
226 228 nt.assert_false(completer.has_open_quotes(s))
227 229
228 230
229 231 def test_has_open_quotes4():
230 232 for s in ['""', '""" """', '"hi" "ipython"']:
231 233 nt.assert_false(completer.has_open_quotes(s))
232 234
233 235
234 236 @knownfailureif(sys.platform == 'win32', "abspath completions fail on Windows")
235 237 def test_abspath_file_completions():
236 238 ip = get_ipython()
237 239 with TemporaryDirectory() as tmpdir:
238 240 prefix = os.path.join(tmpdir, 'foo')
239 241 suffixes = ['1', '2']
240 242 names = [prefix+s for s in suffixes]
241 243 for n in names:
242 244 open(n, 'w').close()
243 245
244 246 # Check simple completion
245 247 c = ip.complete(prefix)[1]
246 248 nt.assert_equal(c, names)
247 249
248 250 # Now check with a function call
249 251 cmd = 'a = f("%s' % prefix
250 252 c = ip.complete(prefix, cmd)[1]
251 253 comp = [prefix+s for s in suffixes]
252 254 nt.assert_equal(c, comp)
253 255
254 256
255 257 def test_local_file_completions():
256 258 ip = get_ipython()
257 259 with TemporaryWorkingDirectory():
258 260 prefix = './foo'
259 261 suffixes = ['1', '2']
260 262 names = [prefix+s for s in suffixes]
261 263 for n in names:
262 264 open(n, 'w').close()
263 265
264 266 # Check simple completion
265 267 c = ip.complete(prefix)[1]
266 268 nt.assert_equal(c, names)
267 269
268 270 # Now check with a function call
269 271 cmd = 'a = f("%s' % prefix
270 272 c = ip.complete(prefix, cmd)[1]
271 273 comp = set(prefix+s for s in suffixes)
272 274 nt.assert_true(comp.issubset(set(c)))
273 275
274 276
275 277 def test_jedi():
276 278 """
277 279 A couple of issue we had with Jedi
278 280 """
279 281 ip = get_ipython()
280 282
281 283 def _test_complete(reason, s, comp, start=None, end=None):
282 284 l = len(s)
283 285 start = start if start is not None else l
284 286 end = end if end is not None else l
285 287 with provisionalcompleter():
286 288 completions = set(ip.Completer.completions(s, l))
287 289 assert_in(Completion(start, end, comp), completions, reason)
288 290
289 291 def _test_not_complete(reason, s, comp):
290 292 l = len(s)
291 293 with provisionalcompleter():
292 294 completions = set(ip.Completer.completions(s, l))
293 295 assert_not_in(Completion(l, l, comp), completions, reason)
294 296
295 297 import jedi
296 298 jedi_version = tuple(int(i) for i in jedi.__version__.split('.')[:3])
297 if jedi_version > (0,10):
299 if jedi_version > (0, 10):
298 300 yield _test_complete, 'jedi >0.9 should complete and not crash', 'a=1;a.', 'real'
299 301 yield _test_complete, 'can infer first argument', 'a=(1,"foo");a[0].', 'real'
300 302 yield _test_complete, 'can infer second argument', 'a=(1,"foo");a[1].', 'capitalize'
301 303 yield _test_complete, 'cover duplicate completions', 'im', 'import', 0, 2
302 304
303 305 yield _test_not_complete, 'does not mix types', 'a=(1,"foo");a[0].', 'capitalize'
304 306
307 def test_deduplicate_completions():
308 """
309 Test that completions are correctly deduplicated (even if ranges are not the same)
310 """
311 ip = get_ipython()
312 ip.ex(textwrap.dedent('''
313 class Z:
314 zoo = 1
315 '''))
316 with provisionalcompleter():
317 l = list(_deduplicate_completions('Z.z', ip.Completer.completions('Z.z', 3)))
318
319 assert len(l) == 1, 'Completions (Z.z<tab>) correctly deduplicate: %s ' % l
320 assert l[0].text == 'zoo' # and not `it.accumulate`
321
305 322
306 323 def test_greedy_completions():
307 324 """
308 325 Test the capability of the Greedy completer.
309 326
310 327 Most of the test here do not really show off the greedy completer, for proof
311 328 each of the text bellow now pass with Jedi. The greedy completer is capable of more.
312 329
313 330 See the :any:`test_dict_key_completion_contexts`
314 331
315 332 """
316 333 ip = get_ipython()
317 334 ip.ex('a=list(range(5))')
318 335 _,c = ip.complete('.',line='a[0].')
319 336 nt.assert_false('.real' in c,
320 337 "Shouldn't have completed on a[0]: %s"%c)
321 338 with greedy_completion(), provisionalcompleter():
322 339 def _(line, cursor_pos, expect, message, completion):
323 340 _,c = ip.complete('.', line=line, cursor_pos=cursor_pos)
324 341 with provisionalcompleter():
325 342 completions = ip.Completer.completions(line, cursor_pos)
326 343 nt.assert_in(expect, c, message%c)
327 344 nt.assert_in(completion, completions)
328 345
329 346 yield _, 'a[0].', 5, 'a[0].real', "Should have completed on a[0].: %s", Completion(5,5, 'real')
330 347 yield _, 'a[0].r', 6, 'a[0].real', "Should have completed on a[0].r: %s", Completion(5,6, 'real')
331 348
332 349 if sys.version_info > (3, 4):
333 350 yield _, 'a[0].from_', 10, 'a[0].from_bytes', "Should have completed on a[0].from_: %s", Completion(5, 10, 'from_bytes')
334 351
335 352
336 353 def test_omit__names():
337 354 # also happens to test IPCompleter as a configurable
338 355 ip = get_ipython()
339 356 ip._hidden_attr = 1
340 357 ip._x = {}
341 358 c = ip.Completer
342 359 ip.ex('ip=get_ipython()')
343 360 cfg = Config()
344 361 cfg.IPCompleter.omit__names = 0
345 362 c.update_config(cfg)
346 363 with provisionalcompleter():
347 364 s,matches = c.complete('ip.')
348 365 completions = set(c.completions('ip.', 3))
349 366
350 367 nt.assert_in('ip.__str__', matches)
351 368 nt.assert_in(Completion(3, 3, '__str__'), completions)
352 369
353 370 nt.assert_in('ip._hidden_attr', matches)
354 371 nt.assert_in(Completion(3,3, "_hidden_attr"), completions)
355 372
356 373
357 374 cfg = Config()
358 375 cfg.IPCompleter.omit__names = 1
359 376 c.update_config(cfg)
360 377 with provisionalcompleter():
361 378 s,matches = c.complete('ip.')
362 379 completions = set(c.completions('ip.', 3))
363 380
364 381 nt.assert_not_in('ip.__str__', matches)
365 382 nt.assert_not_in(Completion(3,3,'__str__'), completions)
366 383
367 384 # nt.assert_in('ip._hidden_attr', matches)
368 385 nt.assert_in(Completion(3,3, "_hidden_attr"), completions)
369 386
370 387 cfg = Config()
371 388 cfg.IPCompleter.omit__names = 2
372 389 c.update_config(cfg)
373 390 with provisionalcompleter():
374 391 s,matches = c.complete('ip.')
375 392 completions = set(c.completions('ip.', 3))
376 393
377 394 nt.assert_not_in('ip.__str__', matches)
378 395 nt.assert_not_in(Completion(3,3,'__str__'), completions)
379 396
380 397 nt.assert_not_in('ip._hidden_attr', matches)
381 398 nt.assert_not_in(Completion(3,3, "_hidden_attr"), completions)
382 399
383 400 with provisionalcompleter():
384 401 s,matches = c.complete('ip._x.')
385 402 completions = set(c.completions('ip._x.', 6))
386 403
387 404 nt.assert_in('ip._x.keys', matches)
388 405 nt.assert_in(Completion(6,6, "keys"), completions)
389 406
390 407 del ip._hidden_attr
391 408 del ip._x
392 409
393 410
394 411 def test_limit_to__all__False_ok():
395 412 """
396 413 Limit to all is deprecated, once we remove it this test can go away.
397 414 """
398 415 ip = get_ipython()
399 416 c = ip.Completer
400 417 ip.ex('class D: x=24')
401 418 ip.ex('d=D()')
402 419 cfg = Config()
403 420 cfg.IPCompleter.limit_to__all__ = False
404 421 c.update_config(cfg)
405 422 s, matches = c.complete('d.')
406 423 nt.assert_in('d.x', matches)
407 424
408 425
409 426 def test_get__all__entries_ok():
410 427 class A(object):
411 428 __all__ = ['x', 1]
412 429 words = completer.get__all__entries(A())
413 430 nt.assert_equal(words, ['x'])
414 431
415 432
416 433 def test_get__all__entries_no__all__ok():
417 434 class A(object):
418 435 pass
419 436 words = completer.get__all__entries(A())
420 437 nt.assert_equal(words, [])
421 438
422 439
423 440 def test_func_kw_completions():
424 441 ip = get_ipython()
425 442 c = ip.Completer
426 443 ip.ex('def myfunc(a=1,b=2): return a+b')
427 444 s, matches = c.complete(None, 'myfunc(1,b')
428 445 nt.assert_in('b=', matches)
429 446 # Simulate completing with cursor right after b (pos==10):
430 447 s, matches = c.complete(None, 'myfunc(1,b)', 10)
431 448 nt.assert_in('b=', matches)
432 449 s, matches = c.complete(None, 'myfunc(a="escaped\\")string",b')
433 450 nt.assert_in('b=', matches)
434 451 #builtin function
435 452 s, matches = c.complete(None, 'min(k, k')
436 453 nt.assert_in('key=', matches)
437 454
438 455
439 456 def test_default_arguments_from_docstring():
440 457 ip = get_ipython()
441 458 c = ip.Completer
442 459 kwd = c._default_arguments_from_docstring(
443 460 'min(iterable[, key=func]) -> value')
444 461 nt.assert_equal(kwd, ['key'])
445 462 #with cython type etc
446 463 kwd = c._default_arguments_from_docstring(
447 464 'Minuit.migrad(self, int ncall=10000, resume=True, int nsplit=1)\n')
448 465 nt.assert_equal(kwd, ['ncall', 'resume', 'nsplit'])
449 466 #white spaces
450 467 kwd = c._default_arguments_from_docstring(
451 468 '\n Minuit.migrad(self, int ncall=10000, resume=True, int nsplit=1)\n')
452 469 nt.assert_equal(kwd, ['ncall', 'resume', 'nsplit'])
453 470
454 471 def test_line_magics():
455 472 ip = get_ipython()
456 473 c = ip.Completer
457 474 s, matches = c.complete(None, 'lsmag')
458 475 nt.assert_in('%lsmagic', matches)
459 476 s, matches = c.complete(None, '%lsmag')
460 477 nt.assert_in('%lsmagic', matches)
461 478
462 479
463 480 def test_cell_magics():
464 481 from IPython.core.magic import register_cell_magic
465 482
466 483 @register_cell_magic
467 484 def _foo_cellm(line, cell):
468 485 pass
469 486
470 487 ip = get_ipython()
471 488 c = ip.Completer
472 489
473 490 s, matches = c.complete(None, '_foo_ce')
474 491 nt.assert_in('%%_foo_cellm', matches)
475 492 s, matches = c.complete(None, '%%_foo_ce')
476 493 nt.assert_in('%%_foo_cellm', matches)
477 494
478 495
479 496 def test_line_cell_magics():
480 497 from IPython.core.magic import register_line_cell_magic
481 498
482 499 @register_line_cell_magic
483 500 def _bar_cellm(line, cell):
484 501 pass
485 502
486 503 ip = get_ipython()
487 504 c = ip.Completer
488 505
489 506 # The policy here is trickier, see comments in completion code. The
490 507 # returned values depend on whether the user passes %% or not explicitly,
491 508 # and this will show a difference if the same name is both a line and cell
492 509 # magic.
493 510 s, matches = c.complete(None, '_bar_ce')
494 511 nt.assert_in('%_bar_cellm', matches)
495 512 nt.assert_in('%%_bar_cellm', matches)
496 513 s, matches = c.complete(None, '%_bar_ce')
497 514 nt.assert_in('%_bar_cellm', matches)
498 515 nt.assert_in('%%_bar_cellm', matches)
499 516 s, matches = c.complete(None, '%%_bar_ce')
500 517 nt.assert_not_in('%_bar_cellm', matches)
501 518 nt.assert_in('%%_bar_cellm', matches)
502 519
503 520
504 521 def test_magic_completion_order():
505 522
506 523 ip = get_ipython()
507 524 c = ip.Completer
508 525
509 526 # Test ordering of magics and non-magics with the same name
510 527 # We want the non-magic first
511 528
512 529 # Before importing matplotlib, there should only be one option:
513 530
514 531 text, matches = c.complete('mat')
515 532 nt.assert_equal(matches, ["%matplotlib"])
516 533
517 534
518 535 ip.run_cell("matplotlib = 1") # introduce name into namespace
519 536
520 537 # After the import, there should be two options, ordered like this:
521 538 text, matches = c.complete('mat')
522 539 nt.assert_equal(matches, ["matplotlib", "%matplotlib"])
523 540
524 541
525 542 ip.run_cell("timeit = 1") # define a user variable called 'timeit'
526 543
527 544 # Order of user variable and line and cell magics with same name:
528 545 text, matches = c.complete('timeit')
529 546 nt.assert_equal(matches, ["timeit", "%timeit", "%%timeit"])
530 547
531 548 def test_match_dict_keys():
532 549 """
533 550 Test that match_dict_keys works on a couple of use case does return what
534 551 expected, and does not crash
535 552 """
536 553 delims = ' \t\n`!@#$^&*()=+[{]}\\|;:\'",<>?'
537 554
538 555
539 556 keys = ['foo', b'far']
540 557 assert match_dict_keys(keys, "b'", delims=delims) == ("'", 2 ,['far'])
541 558 assert match_dict_keys(keys, "b'f", delims=delims) == ("'", 2 ,['far'])
542 559 assert match_dict_keys(keys, 'b"', delims=delims) == ('"', 2 ,['far'])
543 560 assert match_dict_keys(keys, 'b"f', delims=delims) == ('"', 2 ,['far'])
544 561
545 562 assert match_dict_keys(keys, "'", delims=delims) == ("'", 1 ,['foo'])
546 563 assert match_dict_keys(keys, "'f", delims=delims) == ("'", 1 ,['foo'])
547 564 assert match_dict_keys(keys, '"', delims=delims) == ('"', 1 ,['foo'])
548 565 assert match_dict_keys(keys, '"f', delims=delims) == ('"', 1 ,['foo'])
549 566
550 567 match_dict_keys
551 568
552 569
553 570 def test_dict_key_completion_string():
554 571 """Test dictionary key completion for string keys"""
555 572 ip = get_ipython()
556 573 complete = ip.Completer.complete
557 574
558 575 ip.user_ns['d'] = {'abc': None}
559 576
560 577 # check completion at different stages
561 578 _, matches = complete(line_buffer="d[")
562 579 nt.assert_in("'abc'", matches)
563 580 nt.assert_not_in("'abc']", matches)
564 581
565 582 _, matches = complete(line_buffer="d['")
566 583 nt.assert_in("abc", matches)
567 584 nt.assert_not_in("abc']", matches)
568 585
569 586 _, matches = complete(line_buffer="d['a")
570 587 nt.assert_in("abc", matches)
571 588 nt.assert_not_in("abc']", matches)
572 589
573 590 # check use of different quoting
574 591 _, matches = complete(line_buffer="d[\"")
575 592 nt.assert_in("abc", matches)
576 593 nt.assert_not_in('abc\"]', matches)
577 594
578 595 _, matches = complete(line_buffer="d[\"a")
579 596 nt.assert_in("abc", matches)
580 597 nt.assert_not_in('abc\"]', matches)
581 598
582 599 # check sensitivity to following context
583 600 _, matches = complete(line_buffer="d[]", cursor_pos=2)
584 601 nt.assert_in("'abc'", matches)
585 602
586 603 _, matches = complete(line_buffer="d['']", cursor_pos=3)
587 604 nt.assert_in("abc", matches)
588 605 nt.assert_not_in("abc'", matches)
589 606 nt.assert_not_in("abc']", matches)
590 607
591 608 # check multiple solutions are correctly returned and that noise is not
592 609 ip.user_ns['d'] = {'abc': None, 'abd': None, 'bad': None, object(): None,
593 610 5: None}
594 611
595 612 _, matches = complete(line_buffer="d['a")
596 613 nt.assert_in("abc", matches)
597 614 nt.assert_in("abd", matches)
598 615 nt.assert_not_in("bad", matches)
599 616 assert not any(m.endswith((']', '"', "'")) for m in matches), matches
600 617
601 618 # check escaping and whitespace
602 619 ip.user_ns['d'] = {'a\nb': None, 'a\'b': None, 'a"b': None, 'a word': None}
603 620 _, matches = complete(line_buffer="d['a")
604 621 nt.assert_in("a\\nb", matches)
605 622 nt.assert_in("a\\'b", matches)
606 623 nt.assert_in("a\"b", matches)
607 624 nt.assert_in("a word", matches)
608 625 assert not any(m.endswith((']', '"', "'")) for m in matches), matches
609 626
610 627 # - can complete on non-initial word of the string
611 628 _, matches = complete(line_buffer="d['a w")
612 629 nt.assert_in("word", matches)
613 630
614 631 # - understands quote escaping
615 632 _, matches = complete(line_buffer="d['a\\'")
616 633 nt.assert_in("b", matches)
617 634
618 635 # - default quoting should work like repr
619 636 _, matches = complete(line_buffer="d[")
620 637 nt.assert_in("\"a'b\"", matches)
621 638
622 639 # - when opening quote with ", possible to match with unescaped apostrophe
623 640 _, matches = complete(line_buffer="d[\"a'")
624 641 nt.assert_in("b", matches)
625 642
626 643 # need to not split at delims that readline won't split at
627 644 if '-' not in ip.Completer.splitter.delims:
628 645 ip.user_ns['d'] = {'before-after': None}
629 646 _, matches = complete(line_buffer="d['before-af")
630 647 nt.assert_in('before-after', matches)
631 648
632 649 def test_dict_key_completion_contexts():
633 650 """Test expression contexts in which dict key completion occurs"""
634 651 ip = get_ipython()
635 652 complete = ip.Completer.complete
636 653 d = {'abc': None}
637 654 ip.user_ns['d'] = d
638 655
639 656 class C:
640 657 data = d
641 658 ip.user_ns['C'] = C
642 659 ip.user_ns['get'] = lambda: d
643 660
644 661 def assert_no_completion(**kwargs):
645 662 _, matches = complete(**kwargs)
646 663 nt.assert_not_in('abc', matches)
647 664 nt.assert_not_in('abc\'', matches)
648 665 nt.assert_not_in('abc\']', matches)
649 666 nt.assert_not_in('\'abc\'', matches)
650 667 nt.assert_not_in('\'abc\']', matches)
651 668
652 669 def assert_completion(**kwargs):
653 670 _, matches = complete(**kwargs)
654 671 nt.assert_in("'abc'", matches)
655 672 nt.assert_not_in("'abc']", matches)
656 673
657 674 # no completion after string closed, even if reopened
658 675 assert_no_completion(line_buffer="d['a'")
659 676 assert_no_completion(line_buffer="d[\"a\"")
660 677 assert_no_completion(line_buffer="d['a' + ")
661 678 assert_no_completion(line_buffer="d['a' + '")
662 679
663 680 # completion in non-trivial expressions
664 681 assert_completion(line_buffer="+ d[")
665 682 assert_completion(line_buffer="(d[")
666 683 assert_completion(line_buffer="C.data[")
667 684
668 685 # greedy flag
669 686 def assert_completion(**kwargs):
670 687 _, matches = complete(**kwargs)
671 688 nt.assert_in("get()['abc']", matches)
672 689
673 690 assert_no_completion(line_buffer="get()[")
674 691 with greedy_completion():
675 692 assert_completion(line_buffer="get()[")
676 693 assert_completion(line_buffer="get()['")
677 694 assert_completion(line_buffer="get()['a")
678 695 assert_completion(line_buffer="get()['ab")
679 696 assert_completion(line_buffer="get()['abc")
680 697
681 698
682 699
683 700 def test_dict_key_completion_bytes():
684 701 """Test handling of bytes in dict key completion"""
685 702 ip = get_ipython()
686 703 complete = ip.Completer.complete
687 704
688 705 ip.user_ns['d'] = {'abc': None, b'abd': None}
689 706
690 707 _, matches = complete(line_buffer="d[")
691 708 nt.assert_in("'abc'", matches)
692 709 nt.assert_in("b'abd'", matches)
693 710
694 711 if False: # not currently implemented
695 712 _, matches = complete(line_buffer="d[b")
696 713 nt.assert_in("b'abd'", matches)
697 714 nt.assert_not_in("b'abc'", matches)
698 715
699 716 _, matches = complete(line_buffer="d[b'")
700 717 nt.assert_in("abd", matches)
701 718 nt.assert_not_in("abc", matches)
702 719
703 720 _, matches = complete(line_buffer="d[B'")
704 721 nt.assert_in("abd", matches)
705 722 nt.assert_not_in("abc", matches)
706 723
707 724 _, matches = complete(line_buffer="d['")
708 725 nt.assert_in("abc", matches)
709 726 nt.assert_not_in("abd", matches)
710 727
711 728
712 729 def test_dict_key_completion_unicode_py3():
713 730 """Test handling of unicode in dict key completion"""
714 731 ip = get_ipython()
715 732 complete = ip.Completer.complete
716 733
717 734 ip.user_ns['d'] = {u'a\u05d0': None}
718 735
719 736 # query using escape
720 737 if sys.platform != 'win32':
721 738 # Known failure on Windows
722 739 _, matches = complete(line_buffer="d['a\\u05d0")
723 740 nt.assert_in("u05d0", matches) # tokenized after \\
724 741
725 742 # query using character
726 743 _, matches = complete(line_buffer="d['a\u05d0")
727 744 nt.assert_in(u"a\u05d0", matches)
728 745
729 746 with greedy_completion():
730 747 # query using escape
731 748 _, matches = complete(line_buffer="d['a\\u05d0")
732 749 nt.assert_in("d['a\\u05d0']", matches) # tokenized after \\
733 750
734 751 # query using character
735 752 _, matches = complete(line_buffer="d['a\u05d0")
736 753 nt.assert_in(u"d['a\u05d0']", matches)
737 754
738 755
739 756
740 757 @dec.skip_without('numpy')
741 758 def test_struct_array_key_completion():
742 759 """Test dict key completion applies to numpy struct arrays"""
743 760 import numpy
744 761 ip = get_ipython()
745 762 complete = ip.Completer.complete
746 763 ip.user_ns['d'] = numpy.array([], dtype=[('hello', 'f'), ('world', 'f')])
747 764 _, matches = complete(line_buffer="d['")
748 765 nt.assert_in("hello", matches)
749 766 nt.assert_in("world", matches)
750 767 # complete on the numpy struct itself
751 768 dt = numpy.dtype([('my_head', [('my_dt', '>u4'), ('my_df', '>u4')]),
752 769 ('my_data', '>f4', 5)])
753 770 x = numpy.zeros(2, dtype=dt)
754 771 ip.user_ns['d'] = x[1]
755 772 _, matches = complete(line_buffer="d['")
756 773 nt.assert_in("my_head", matches)
757 774 nt.assert_in("my_data", matches)
758 775 # complete on a nested level
759 776 with greedy_completion():
760 777 ip.user_ns['d'] = numpy.zeros(2, dtype=dt)
761 778 _, matches = complete(line_buffer="d[1]['my_head']['")
762 779 nt.assert_true(any(["my_dt" in m for m in matches]))
763 780 nt.assert_true(any(["my_df" in m for m in matches]))
764 781
765 782
766 783 @dec.skip_without('pandas')
767 784 def test_dataframe_key_completion():
768 785 """Test dict key completion applies to pandas DataFrames"""
769 786 import pandas
770 787 ip = get_ipython()
771 788 complete = ip.Completer.complete
772 789 ip.user_ns['d'] = pandas.DataFrame({'hello': [1], 'world': [2]})
773 790 _, matches = complete(line_buffer="d['")
774 791 nt.assert_in("hello", matches)
775 792 nt.assert_in("world", matches)
776 793
777 794
778 795 def test_dict_key_completion_invalids():
779 796 """Smoke test cases dict key completion can't handle"""
780 797 ip = get_ipython()
781 798 complete = ip.Completer.complete
782 799
783 800 ip.user_ns['no_getitem'] = None
784 801 ip.user_ns['no_keys'] = []
785 802 ip.user_ns['cant_call_keys'] = dict
786 803 ip.user_ns['empty'] = {}
787 804 ip.user_ns['d'] = {'abc': 5}
788 805
789 806 _, matches = complete(line_buffer="no_getitem['")
790 807 _, matches = complete(line_buffer="no_keys['")
791 808 _, matches = complete(line_buffer="cant_call_keys['")
792 809 _, matches = complete(line_buffer="empty['")
793 810 _, matches = complete(line_buffer="name_error['")
794 811 _, matches = complete(line_buffer="d['\\") # incomplete escape
795 812
796 813 class KeyCompletable(object):
797 814 def __init__(self, things=()):
798 815 self.things = things
799 816
800 817 def _ipython_key_completions_(self):
801 818 return list(self.things)
802 819
803 820 def test_object_key_completion():
804 821 ip = get_ipython()
805 822 ip.user_ns['key_completable'] = KeyCompletable(['qwerty', 'qwick'])
806 823
807 824 _, matches = ip.Completer.complete(line_buffer="key_completable['qw")
808 825 nt.assert_in('qwerty', matches)
809 826 nt.assert_in('qwick', matches)
810 827
811 828
812 829 def test_tryimport():
813 830 """
814 831 Test that try-import don't crash on trailing dot, and import modules before
815 832 """
816 833 from IPython.core.completerlib import try_import
817 834 assert(try_import("IPython."))
818 835
819 836
820 837 def test_aimport_module_completer():
821 838 ip = get_ipython()
822 839 _, matches = ip.complete('i', '%aimport i')
823 840 nt.assert_in('io', matches)
824 841 nt.assert_not_in('int', matches)
825 842
826 843 def test_nested_import_module_completer():
827 844 ip = get_ipython()
828 845 _, matches = ip.complete(None, 'import IPython.co', 17)
829 846 nt.assert_in('IPython.core', matches)
830 847 nt.assert_not_in('import IPython.core', matches)
831 848 nt.assert_not_in('IPython.display', matches)
832 849
833 850 def test_import_module_completer():
834 851 ip = get_ipython()
835 852 _, matches = ip.complete('i', 'import i')
836 853 nt.assert_in('io', matches)
837 854 nt.assert_not_in('int', matches)
838 855
839 856 def test_from_module_completer():
840 857 ip = get_ipython()
841 858 _, matches = ip.complete('B', 'from io import B', 16)
842 859 nt.assert_in('BytesIO', matches)
843 860 nt.assert_not_in('BaseException', matches)
@@ -1,126 +1,128 b''
1 1 """prompt-toolkit utilities
2 2
3 3 Everything in this module is a private API,
4 4 not to be used outside IPython.
5 5 """
6 6
7 7 # Copyright (c) IPython Development Team.
8 8 # Distributed under the terms of the Modified BSD License.
9 9
10 10 import unicodedata
11 11 from wcwidth import wcwidth
12 12
13 from IPython.core.completer import IPCompleter, provisionalcompleter, rectify_completions, cursor_to_position
13 from IPython.core.completer import (
14 IPCompleter, provisionalcompleter, rectify_completions, cursor_to_position,
15 _deduplicate_completions)
14 16 from prompt_toolkit.completion import Completer, Completion
15 17 from prompt_toolkit.layout.lexers import Lexer
16 18 from prompt_toolkit.layout.lexers import PygmentsLexer
17 19
18 20 import pygments.lexers as pygments_lexers
19 21
20 22 _completion_sentinel = object()
21 23
22 24
23 25
24 26
25 27 class IPythonPTCompleter(Completer):
26 28 """Adaptor to provide IPython completions to prompt_toolkit"""
27 29 def __init__(self, ipy_completer=None, shell=None, patch_stdout=None):
28 30 if shell is None and ipy_completer is None:
29 31 raise TypeError("Please pass shell=an InteractiveShell instance.")
30 32 self._ipy_completer = ipy_completer
31 33 self.shell = shell
32 34 if patch_stdout is None:
33 35 raise TypeError("Please pass patch_stdout")
34 36 self.patch_stdout = patch_stdout
35 37
36 38 @property
37 39 def ipy_completer(self):
38 40 if self._ipy_completer:
39 41 return self._ipy_completer
40 42 else:
41 43 return self.shell.Completer
42 44
43 45 def get_completions(self, document, complete_event):
44 46 if not document.current_line.strip():
45 47 return
46 48 # Some bits of our completion system may print stuff (e.g. if a module
47 49 # is imported). This context manager ensures that doesn't interfere with
48 50 # the prompt.
49 51
50 52 with self.patch_stdout(), provisionalcompleter():
51 53 body = document.text
52 54 cursor_row = document.cursor_position_row
53 55 cursor_col = document.cursor_position_col
54 56 cursor_position = document.cursor_position
55 57 offset = cursor_to_position(body, cursor_row, cursor_col)
56 58 yield from self._get_completions(body, offset, cursor_position, self.ipy_completer)
57 59
58 60 @staticmethod
59 61 def _get_completions(body, offset, cursor_position, ipyc):
60 62 """
61 63 Private equivalent of get_completions() use only for unit_testing.
62 64 """
63 65 debug = getattr(ipyc, 'debug', False)
64 completions = rectify_completions(
65 body, ipyc.completions(body, offset), _debug=debug)
66 completions = _deduplicate_completions(
67 body, ipyc.completions(body, offset))
66 68 for c in completions:
67 69 if not c.text:
68 70 # Guard against completion machinery giving us an empty string.
69 71 continue
70 72 text = unicodedata.normalize('NFC', c.text)
71 73 # When the first character of the completion has a zero length,
72 74 # then it's probably a decomposed unicode character. E.g. caused by
73 75 # the "\dot" completion. Try to compose again with the previous
74 76 # character.
75 77 if wcwidth(text[0]) == 0:
76 78 if cursor_position + c.start > 0:
77 79 char_before = body[c.start - 1]
78 80 fixed_text = unicodedata.normalize(
79 81 'NFC', char_before + text)
80 82
81 83 # Yield the modified completion instead, if this worked.
82 84 if wcwidth(text[0:1]) == 1:
83 85 yield Completion(fixed_text, start_position=c.start - offset - 1)
84 86 continue
85 87
86 88 # TODO: Use Jedi to determine meta_text
87 89 # (Jedi currently has a bug that results in incorrect information.)
88 90 # meta_text = ''
89 91 # yield Completion(m, start_position=start_pos,
90 92 # display_meta=meta_text)
91 93 yield Completion(c.text, start_position=c.start - offset, display_meta=c.type)
92 94
93 95 class IPythonPTLexer(Lexer):
94 96 """
95 97 Wrapper around PythonLexer and BashLexer.
96 98 """
97 99 def __init__(self):
98 100 l = pygments_lexers
99 101 self.python_lexer = PygmentsLexer(l.Python3Lexer)
100 102 self.shell_lexer = PygmentsLexer(l.BashLexer)
101 103
102 104 self.magic_lexers = {
103 105 'HTML': PygmentsLexer(l.HtmlLexer),
104 106 'html': PygmentsLexer(l.HtmlLexer),
105 107 'javascript': PygmentsLexer(l.JavascriptLexer),
106 108 'js': PygmentsLexer(l.JavascriptLexer),
107 109 'perl': PygmentsLexer(l.PerlLexer),
108 110 'ruby': PygmentsLexer(l.RubyLexer),
109 111 'latex': PygmentsLexer(l.TexLexer),
110 112 }
111 113
112 114 def lex_document(self, cli, document):
113 115 text = document.text.lstrip()
114 116
115 117 lexer = self.python_lexer
116 118
117 119 if text.startswith('!') or text.startswith('%%bash'):
118 120 lexer = self.shell_lexer
119 121
120 122 elif text.startswith('%%'):
121 123 for magic, l in self.magic_lexers.items():
122 124 if text.startswith('%%' + magic):
123 125 lexer = l
124 126 break
125 127
126 128 return lexer.lex_document(cli, document)
General Comments 0
You need to be logged in to leave comments. Login now