##// END OF EJS Templates
Protect against jedi failing to get the type of a completion...
Matthias Bussonnier -
Show More
@@ -1,1736 +1,1742 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 _IC = Iterator[Completion]
348 348
349 349 def rectify_completions(text:str, completion:_IC, *, _debug=False)->_IC:
350 350 """
351 351 Rectify a set of completion to all have the same ``start`` and ``end``
352 352
353 353 .. warning:: Unstable
354 354
355 355 This function is unstable, API may change without warning.
356 356 It will also raise unless use in proper context manager.
357 357
358 358 Parameters
359 359 ----------
360 360 text: str
361 361 text that should be completed.
362 362 completion: Iterator[Completion]
363 363 iterator over the completions to rectify
364 364
365 365
366 366 :any:`jedi.api.classes.Completion` s returned by Jedi may not have the same start and end, though
367 367 the Jupyter Protocol requires them to behave like so. This will readjust
368 368 the completion to have the same ``start`` and ``end` by padding both
369 369 extremities with surrounding text.
370 370
371 371 During stabilisation should support a ``_debug`` option to log which
372 372 completion are return by the IPython completer and not found in Jedi in
373 373 order to make upstream bug report.
374 374 """
375 375 warnings.warn("`rectify_completions` is a provisional API (as of IPython 6.0). "
376 376 "It may change without warnings. "
377 377 "Use in corresponding context manager.",
378 378 category=ProvisionalCompleterWarning, stacklevel=2)
379 379
380 380 completions = list(completion)
381 381 if not completions:
382 382 return
383 383 starts = (c.start for c in completions)
384 384 ends = (c.end for c in completions)
385 385
386 386 new_start = min(starts)
387 387 new_end = max(ends)
388 388
389 389 seen_jedi = set()
390 390 seen_python_matches = set()
391 391 for c in completions:
392 392 new_text = text[new_start:c.start] + c.text + text[c.end:new_end]
393 393 if c._origin == 'jedi':
394 394 seen_jedi.add(new_text)
395 395 elif c._origin == 'IPCompleter.python_matches':
396 396 seen_python_matches.add(new_text)
397 397 yield Completion(new_start, new_end, new_text, type=c.type, _origin=c._origin)
398 398 diff = seen_python_matches.difference(seen_jedi)
399 399 if diff and _debug:
400 400 print('IPython.python matches have extras:', diff)
401 401
402 402
403 403 if sys.platform == 'win32':
404 404 DELIMS = ' \t\n`!@#$^&*()=+[{]}|;\'",<>?'
405 405 else:
406 406 DELIMS = ' \t\n`!@#$^&*()=+[{]}\\|;:\'",<>?'
407 407
408 408 GREEDY_DELIMS = ' =\r\n'
409 409
410 410
411 411 class CompletionSplitter(object):
412 412 """An object to split an input line in a manner similar to readline.
413 413
414 414 By having our own implementation, we can expose readline-like completion in
415 415 a uniform manner to all frontends. This object only needs to be given the
416 416 line of text to be split and the cursor position on said line, and it
417 417 returns the 'word' to be completed on at the cursor after splitting the
418 418 entire line.
419 419
420 420 What characters are used as splitting delimiters can be controlled by
421 421 setting the ``delims`` attribute (this is a property that internally
422 422 automatically builds the necessary regular expression)"""
423 423
424 424 # Private interface
425 425
426 426 # A string of delimiter characters. The default value makes sense for
427 427 # IPython's most typical usage patterns.
428 428 _delims = DELIMS
429 429
430 430 # The expression (a normal string) to be compiled into a regular expression
431 431 # for actual splitting. We store it as an attribute mostly for ease of
432 432 # debugging, since this type of code can be so tricky to debug.
433 433 _delim_expr = None
434 434
435 435 # The regular expression that does the actual splitting
436 436 _delim_re = None
437 437
438 438 def __init__(self, delims=None):
439 439 delims = CompletionSplitter._delims if delims is None else delims
440 440 self.delims = delims
441 441
442 442 @property
443 443 def delims(self):
444 444 """Return the string of delimiter characters."""
445 445 return self._delims
446 446
447 447 @delims.setter
448 448 def delims(self, delims):
449 449 """Set the delimiters for line splitting."""
450 450 expr = '[' + ''.join('\\'+ c for c in delims) + ']'
451 451 self._delim_re = re.compile(expr)
452 452 self._delims = delims
453 453 self._delim_expr = expr
454 454
455 455 def split_line(self, line, cursor_pos=None):
456 456 """Split a line of text with a cursor at the given position.
457 457 """
458 458 l = line if cursor_pos is None else line[:cursor_pos]
459 459 return self._delim_re.split(l)[-1]
460 460
461 461
462 462
463 463 class Completer(Configurable):
464 464
465 465 greedy = Bool(False,
466 466 help="""Activate greedy completion
467 467 PENDING DEPRECTION. this is now mostly taken care of with Jedi.
468 468
469 469 This will enable completion on elements of lists, results of function calls, etc.,
470 470 but can be unsafe because the code is actually evaluated on TAB.
471 471 """
472 472 ).tag(config=True)
473 473
474 474 use_jedi = Bool(default_value=JEDI_INSTALLED,
475 475 help="Experimental: Use Jedi to generate autocompletions. "
476 476 "Default to True if jedi is installed").tag(config=True)
477 477
478 478 jedi_compute_type_timeout = Int(default_value=400,
479 479 help="""Experimental: restrict time (in milliseconds) during which Jedi can compute types.
480 480 Set to 0 to stop computing types. Non-zero value lower than 100ms may hurt
481 481 performance by preventing jedi to build its cache.
482 482 """).tag(config=True)
483 483
484 484 debug = Bool(default_value=False,
485 485 help='Enable debug for the Completer. Mostly print extra '
486 486 'information for experimental jedi integration.')\
487 487 .tag(config=True)
488 488
489 489
490 490 def __init__(self, namespace=None, global_namespace=None, **kwargs):
491 491 """Create a new completer for the command line.
492 492
493 493 Completer(namespace=ns, global_namespace=ns2) -> completer instance.
494 494
495 495 If unspecified, the default namespace where completions are performed
496 496 is __main__ (technically, __main__.__dict__). Namespaces should be
497 497 given as dictionaries.
498 498
499 499 An optional second namespace can be given. This allows the completer
500 500 to handle cases where both the local and global scopes need to be
501 501 distinguished.
502 502 """
503 503
504 504 # Don't bind to namespace quite yet, but flag whether the user wants a
505 505 # specific namespace or to use __main__.__dict__. This will allow us
506 506 # to bind to __main__.__dict__ at completion time, not now.
507 507 if namespace is None:
508 508 self.use_main_ns = True
509 509 else:
510 510 self.use_main_ns = False
511 511 self.namespace = namespace
512 512
513 513 # The global namespace, if given, can be bound directly
514 514 if global_namespace is None:
515 515 self.global_namespace = {}
516 516 else:
517 517 self.global_namespace = global_namespace
518 518
519 519 super(Completer, self).__init__(**kwargs)
520 520
521 521 def complete(self, text, state):
522 522 """Return the next possible completion for 'text'.
523 523
524 524 This is called successively with state == 0, 1, 2, ... until it
525 525 returns None. The completion should begin with 'text'.
526 526
527 527 """
528 528 if self.use_main_ns:
529 529 self.namespace = __main__.__dict__
530 530
531 531 if state == 0:
532 532 if "." in text:
533 533 self.matches = self.attr_matches(text)
534 534 else:
535 535 self.matches = self.global_matches(text)
536 536 try:
537 537 return self.matches[state]
538 538 except IndexError:
539 539 return None
540 540
541 541 def global_matches(self, text):
542 542 """Compute matches when text is a simple name.
543 543
544 544 Return a list of all keywords, built-in functions and names currently
545 545 defined in self.namespace or self.global_namespace that match.
546 546
547 547 """
548 548 matches = []
549 549 match_append = matches.append
550 550 n = len(text)
551 551 for lst in [keyword.kwlist,
552 552 builtin_mod.__dict__.keys(),
553 553 self.namespace.keys(),
554 554 self.global_namespace.keys()]:
555 555 for word in lst:
556 556 if word[:n] == text and word != "__builtins__":
557 557 match_append(word)
558 558 return [cast_unicode_py2(m) for m in matches]
559 559
560 560 def attr_matches(self, text):
561 561 """Compute matches when text contains a dot.
562 562
563 563 Assuming the text is of the form NAME.NAME....[NAME], and is
564 564 evaluatable in self.namespace or self.global_namespace, it will be
565 565 evaluated and its attributes (as revealed by dir()) are used as
566 566 possible completions. (For class instances, class members are are
567 567 also considered.)
568 568
569 569 WARNING: this can still invoke arbitrary C code, if an object
570 570 with a __getattr__ hook is evaluated.
571 571
572 572 """
573 573
574 574 # Another option, seems to work great. Catches things like ''.<tab>
575 575 m = re.match(r"(\S+(\.\w+)*)\.(\w*)$", text)
576 576
577 577 if m:
578 578 expr, attr = m.group(1, 3)
579 579 elif self.greedy:
580 580 m2 = re.match(r"(.+)\.(\w*)$", self.line_buffer)
581 581 if not m2:
582 582 return []
583 583 expr, attr = m2.group(1,2)
584 584 else:
585 585 return []
586 586
587 587 try:
588 588 obj = eval(expr, self.namespace)
589 589 except:
590 590 try:
591 591 obj = eval(expr, self.global_namespace)
592 592 except:
593 593 return []
594 594
595 595 if self.limit_to__all__ and hasattr(obj, '__all__'):
596 596 words = get__all__entries(obj)
597 597 else:
598 598 words = dir2(obj)
599 599
600 600 try:
601 601 words = generics.complete_object(obj, words)
602 602 except TryNext:
603 603 pass
604 604 except AssertionError:
605 605 raise
606 606 except Exception:
607 607 # Silence errors from completion function
608 608 #raise # dbg
609 609 pass
610 610 # Build match list to return
611 611 n = len(attr)
612 612 return [u"%s.%s" % (expr, w) for w in words if w[:n] == attr ]
613 613
614 614
615 615 def get__all__entries(obj):
616 616 """returns the strings in the __all__ attribute"""
617 617 try:
618 618 words = getattr(obj, '__all__')
619 619 except:
620 620 return []
621 621
622 622 return [cast_unicode_py2(w) for w in words if isinstance(w, str)]
623 623
624 624
625 625 def match_dict_keys(keys, prefix, delims):
626 626 """Used by dict_key_matches, matching the prefix to a list of keys"""
627 627 if not prefix:
628 628 return None, 0, [repr(k) for k in keys
629 629 if isinstance(k, (str, bytes))]
630 630 quote_match = re.search('["\']', prefix)
631 631 quote = quote_match.group()
632 632 try:
633 633 prefix_str = eval(prefix + quote, {})
634 634 except Exception:
635 635 return None, 0, []
636 636
637 637 pattern = '[^' + ''.join('\\' + c for c in delims) + ']*$'
638 638 token_match = re.search(pattern, prefix, re.UNICODE)
639 639 token_start = token_match.start()
640 640 token_prefix = token_match.group()
641 641
642 642 # TODO: support bytes in Py3k
643 643 matched = []
644 644 for key in keys:
645 645 try:
646 646 if not key.startswith(prefix_str):
647 647 continue
648 648 except (AttributeError, TypeError, UnicodeError):
649 649 # Python 3+ TypeError on b'a'.startswith('a') or vice-versa
650 650 continue
651 651
652 652 # reformat remainder of key to begin with prefix
653 653 rem = key[len(prefix_str):]
654 654 # force repr wrapped in '
655 655 rem_repr = repr(rem + '"')
656 656 if rem_repr.startswith('u') and prefix[0] not in 'uU':
657 657 # Found key is unicode, but prefix is Py2 string.
658 658 # Therefore attempt to interpret key as string.
659 659 try:
660 660 rem_repr = repr(rem.encode('ascii') + '"')
661 661 except UnicodeEncodeError:
662 662 continue
663 663
664 664 rem_repr = rem_repr[1 + rem_repr.index("'"):-2]
665 665 if quote == '"':
666 666 # The entered prefix is quoted with ",
667 667 # but the match is quoted with '.
668 668 # A contained " hence needs escaping for comparison:
669 669 rem_repr = rem_repr.replace('"', '\\"')
670 670
671 671 # then reinsert prefix from start of token
672 672 matched.append('%s%s' % (token_prefix, rem_repr))
673 673 return quote, token_start, matched
674 674
675 675
676 676 def cursor_to_position(text:int, line:int, column:int)->int:
677 677 """
678 678
679 679 Convert the (line,column) position of the cursor in text to an offset in a
680 680 string.
681 681
682 682 Parameter
683 683 ---------
684 684
685 685 text : str
686 686 The text in which to calculate the cursor offset
687 687 line : int
688 688 Line of the cursor; 0-indexed
689 689 column : int
690 690 Column of the cursor 0-indexed
691 691
692 692 Return
693 693 ------
694 694 Position of the cursor in ``text``, 0-indexed.
695 695
696 696 See Also
697 697 --------
698 698 position_to_cursor: reciprocal of this function
699 699
700 700 """
701 701 lines = text.split('\n')
702 702 assert line <= len(lines), '{} <= {}'.format(str(line), str(len(lines)))
703 703
704 704 return sum(len(l) + 1 for l in lines[:line]) + column
705 705
706 706 def position_to_cursor(text:str, offset:int)->(int, int):
707 707 """
708 708 Convert the position of the cursor in text (0 indexed) to a line
709 709 number(0-indexed) and a column number (0-indexed) pair
710 710
711 711 Position should be a valid position in ``text``.
712 712
713 713 Parameter
714 714 ---------
715 715
716 716 text : str
717 717 The text in which to calculate the cursor offset
718 718 offset : int
719 719 Position of the cursor in ``text``, 0-indexed.
720 720
721 721 Return
722 722 ------
723 723 (line, column) : (int, int)
724 724 Line of the cursor; 0-indexed, column of the cursor 0-indexed
725 725
726 726
727 727 See Also
728 728 --------
729 729 cursor_to_position : reciprocal of this function
730 730
731 731
732 732 """
733 733
734 734 assert 0 < offset <= len(text) , "0 < %s <= %s" % (offset , len(text))
735 735
736 736 before = text[:offset]
737 737 blines = before.split('\n') # ! splitnes trim trailing \n
738 738 line = before.count('\n')
739 739 col = len(blines[-1])
740 740 return line, col
741 741
742 742
743 743 def _safe_isinstance(obj, module, class_name):
744 744 """Checks if obj is an instance of module.class_name if loaded
745 745 """
746 746 return (module in sys.modules and
747 747 isinstance(obj, getattr(import_module(module), class_name)))
748 748
749 749
750 750 def back_unicode_name_matches(text):
751 751 u"""Match unicode characters back to unicode name
752 752
753 753 This does ``β˜ƒ`` -> ``\\snowman``
754 754
755 755 Note that snowman is not a valid python3 combining character but will be expanded.
756 756 Though it will not recombine back to the snowman character by the completion machinery.
757 757
758 758 This will not either back-complete standard sequences like \\n, \\b ...
759 759
760 760 Used on Python 3 only.
761 761 """
762 762 if len(text)<2:
763 763 return u'', ()
764 764 maybe_slash = text[-2]
765 765 if maybe_slash != '\\':
766 766 return u'', ()
767 767
768 768 char = text[-1]
769 769 # no expand on quote for completion in strings.
770 770 # nor backcomplete standard ascii keys
771 771 if char in string.ascii_letters or char in ['"',"'"]:
772 772 return u'', ()
773 773 try :
774 774 unic = unicodedata.name(char)
775 775 return '\\'+char,['\\'+unic]
776 776 except KeyError:
777 777 pass
778 778 return u'', ()
779 779
780 780 def back_latex_name_matches(text:str):
781 781 """Match latex characters back to unicode name
782 782
783 783 This does ``\\β„΅`` -> ``\\aleph``
784 784
785 785 Used on Python 3 only.
786 786 """
787 787 if len(text)<2:
788 788 return u'', ()
789 789 maybe_slash = text[-2]
790 790 if maybe_slash != '\\':
791 791 return u'', ()
792 792
793 793
794 794 char = text[-1]
795 795 # no expand on quote for completion in strings.
796 796 # nor backcomplete standard ascii keys
797 797 if char in string.ascii_letters or char in ['"',"'"]:
798 798 return u'', ()
799 799 try :
800 800 latex = reverse_latex_symbol[char]
801 801 # '\\' replace the \ as well
802 802 return '\\'+char,[latex]
803 803 except KeyError:
804 804 pass
805 805 return u'', ()
806 806
807 807
808 808 class IPCompleter(Completer):
809 809 """Extension of the completer class with IPython-specific features"""
810 810
811 811 @observe('greedy')
812 812 def _greedy_changed(self, change):
813 813 """update the splitter and readline delims when greedy is changed"""
814 814 if change['new']:
815 815 self.splitter.delims = GREEDY_DELIMS
816 816 else:
817 817 self.splitter.delims = DELIMS
818 818
819 819 merge_completions = Bool(True,
820 820 help="""Whether to merge completion results into a single list
821 821
822 822 If False, only the completion results from the first non-empty
823 823 completer will be returned.
824 824 """
825 825 ).tag(config=True)
826 826 omit__names = Enum((0,1,2), default_value=2,
827 827 help="""Instruct the completer to omit private method names
828 828
829 829 Specifically, when completing on ``object.<tab>``.
830 830
831 831 When 2 [default]: all names that start with '_' will be excluded.
832 832
833 833 When 1: all 'magic' names (``__foo__``) will be excluded.
834 834
835 835 When 0: nothing will be excluded.
836 836 """
837 837 ).tag(config=True)
838 838 limit_to__all__ = Bool(False,
839 839 help="""
840 840 DEPRECATED as of version 5.0.
841 841
842 842 Instruct the completer to use __all__ for the completion
843 843
844 844 Specifically, when completing on ``object.<tab>``.
845 845
846 846 When True: only those names in obj.__all__ will be included.
847 847
848 848 When False [default]: the __all__ attribute is ignored
849 849 """,
850 850 ).tag(config=True)
851 851
852 852 @observe('limit_to__all__')
853 853 def _limit_to_all_changed(self, change):
854 854 warnings.warn('`IPython.core.IPCompleter.limit_to__all__` configuration '
855 855 'value has been deprecated since IPython 5.0, will be made to have '
856 856 'no effects and then removed in future version of IPython.',
857 857 UserWarning)
858 858
859 859 def __init__(self, shell=None, namespace=None, global_namespace=None,
860 860 use_readline=_deprecation_readline_sentinel, config=None, **kwargs):
861 861 """IPCompleter() -> completer
862 862
863 863 Return a completer object.
864 864
865 865 Parameters
866 866 ----------
867 867
868 868 shell
869 869 a pointer to the ipython shell itself. This is needed
870 870 because this completer knows about magic functions, and those can
871 871 only be accessed via the ipython instance.
872 872
873 873 namespace : dict, optional
874 874 an optional dict where completions are performed.
875 875
876 876 global_namespace : dict, optional
877 877 secondary optional dict for completions, to
878 878 handle cases (such as IPython embedded inside functions) where
879 879 both Python scopes are visible.
880 880
881 881 use_readline : bool, optional
882 882 DEPRECATED, ignored since IPython 6.0, will have no effects
883 883 """
884 884
885 885 self.magic_escape = ESC_MAGIC
886 886 self.splitter = CompletionSplitter()
887 887
888 888 if use_readline is not _deprecation_readline_sentinel:
889 889 warnings.warn('The `use_readline` parameter is deprecated and ignored since IPython 6.0.',
890 890 DeprecationWarning, stacklevel=2)
891 891
892 892 # _greedy_changed() depends on splitter and readline being defined:
893 893 Completer.__init__(self, namespace=namespace, global_namespace=global_namespace,
894 894 config=config, **kwargs)
895 895
896 896 # List where completion matches will be stored
897 897 self.matches = []
898 898 self.shell = shell
899 899 # Regexp to split filenames with spaces in them
900 900 self.space_name_re = re.compile(r'([^\\] )')
901 901 # Hold a local ref. to glob.glob for speed
902 902 self.glob = glob.glob
903 903
904 904 # Determine if we are running on 'dumb' terminals, like (X)Emacs
905 905 # buffers, to avoid completion problems.
906 906 term = os.environ.get('TERM','xterm')
907 907 self.dumb_terminal = term in ['dumb','emacs']
908 908
909 909 # Special handling of backslashes needed in win32 platforms
910 910 if sys.platform == "win32":
911 911 self.clean_glob = self._clean_glob_win32
912 912 else:
913 913 self.clean_glob = self._clean_glob
914 914
915 915 #regexp to parse docstring for function signature
916 916 self.docstring_sig_re = re.compile(r'^[\w|\s.]+\(([^)]*)\).*')
917 917 self.docstring_kwd_re = re.compile(r'[\s|\[]*(\w+)(?:\s*=\s*.*)')
918 918 #use this if positional argument name is also needed
919 919 #= re.compile(r'[\s|\[]*(\w+)(?:\s*=?\s*.*)')
920 920
921 921 # All active matcher routines for completion
922 922 self.matchers = [
923 923 self.python_matches,
924 924 self.file_matches,
925 925 self.magic_matches,
926 926 self.python_func_kw_matches,
927 927 self.dict_key_matches,
928 928 ]
929 929
930 930 # This is set externally by InteractiveShell
931 931 self.custom_completers = None
932 932
933 933 def all_completions(self, text):
934 934 """
935 935 Wrapper around the complete method for the benefit of emacs.
936 936 """
937 937 return self.complete(text)[1]
938 938
939 939 def _clean_glob(self, text):
940 940 return self.glob("%s*" % text)
941 941
942 942 def _clean_glob_win32(self,text):
943 943 return [f.replace("\\","/")
944 944 for f in self.glob("%s*" % text)]
945 945
946 946 def file_matches(self, text):
947 947 """Match filenames, expanding ~USER type strings.
948 948
949 949 Most of the seemingly convoluted logic in this completer is an
950 950 attempt to handle filenames with spaces in them. And yet it's not
951 951 quite perfect, because Python's readline doesn't expose all of the
952 952 GNU readline details needed for this to be done correctly.
953 953
954 954 For a filename with a space in it, the printed completions will be
955 955 only the parts after what's already been typed (instead of the
956 956 full completions, as is normally done). I don't think with the
957 957 current (as of Python 2.3) Python readline it's possible to do
958 958 better."""
959 959
960 960 # chars that require escaping with backslash - i.e. chars
961 961 # that readline treats incorrectly as delimiters, but we
962 962 # don't want to treat as delimiters in filename matching
963 963 # when escaped with backslash
964 964 if text.startswith('!'):
965 965 text = text[1:]
966 966 text_prefix = u'!'
967 967 else:
968 968 text_prefix = u''
969 969
970 970 text_until_cursor = self.text_until_cursor
971 971 # track strings with open quotes
972 972 open_quotes = has_open_quotes(text_until_cursor)
973 973
974 974 if '(' in text_until_cursor or '[' in text_until_cursor:
975 975 lsplit = text
976 976 else:
977 977 try:
978 978 # arg_split ~ shlex.split, but with unicode bugs fixed by us
979 979 lsplit = arg_split(text_until_cursor)[-1]
980 980 except ValueError:
981 981 # typically an unmatched ", or backslash without escaped char.
982 982 if open_quotes:
983 983 lsplit = text_until_cursor.split(open_quotes)[-1]
984 984 else:
985 985 return []
986 986 except IndexError:
987 987 # tab pressed on empty line
988 988 lsplit = ""
989 989
990 990 if not open_quotes and lsplit != protect_filename(lsplit):
991 991 # if protectables are found, do matching on the whole escaped name
992 992 has_protectables = True
993 993 text0,text = text,lsplit
994 994 else:
995 995 has_protectables = False
996 996 text = os.path.expanduser(text)
997 997
998 998 if text == "":
999 999 return [text_prefix + cast_unicode_py2(protect_filename(f)) for f in self.glob("*")]
1000 1000
1001 1001 # Compute the matches from the filesystem
1002 1002 if sys.platform == 'win32':
1003 1003 m0 = self.clean_glob(text)
1004 1004 else:
1005 1005 m0 = self.clean_glob(text.replace('\\', ''))
1006 1006
1007 1007 if has_protectables:
1008 1008 # If we had protectables, we need to revert our changes to the
1009 1009 # beginning of filename so that we don't double-write the part
1010 1010 # of the filename we have so far
1011 1011 len_lsplit = len(lsplit)
1012 1012 matches = [text_prefix + text0 +
1013 1013 protect_filename(f[len_lsplit:]) for f in m0]
1014 1014 else:
1015 1015 if open_quotes:
1016 1016 # if we have a string with an open quote, we don't need to
1017 1017 # protect the names at all (and we _shouldn't_, as it
1018 1018 # would cause bugs when the filesystem call is made).
1019 1019 matches = m0
1020 1020 else:
1021 1021 matches = [text_prefix +
1022 1022 protect_filename(f) for f in m0]
1023 1023
1024 1024 # Mark directories in input list by appending '/' to their names.
1025 1025 return [cast_unicode_py2(x+'/') if os.path.isdir(x) else x for x in matches]
1026 1026
1027 1027 def magic_matches(self, text):
1028 1028 """Match magics"""
1029 1029 # Get all shell magics now rather than statically, so magics loaded at
1030 1030 # runtime show up too.
1031 1031 lsm = self.shell.magics_manager.lsmagic()
1032 1032 line_magics = lsm['line']
1033 1033 cell_magics = lsm['cell']
1034 1034 pre = self.magic_escape
1035 1035 pre2 = pre+pre
1036 1036
1037 1037 # Completion logic:
1038 1038 # - user gives %%: only do cell magics
1039 1039 # - user gives %: do both line and cell magics
1040 1040 # - no prefix: do both
1041 1041 # In other words, line magics are skipped if the user gives %% explicitly
1042 1042 bare_text = text.lstrip(pre)
1043 1043 comp = [ pre2+m for m in cell_magics if m.startswith(bare_text)]
1044 1044 if not text.startswith(pre2):
1045 1045 comp += [ pre+m for m in line_magics if m.startswith(bare_text)]
1046 1046 return [cast_unicode_py2(c) for c in comp]
1047 1047
1048 1048 def _jedi_matches(self, cursor_column:int, cursor_line:int, text:str):
1049 1049 """
1050 1050
1051 1051 Return a list of :any:`jedi.api.Completions` object from a ``text`` and
1052 1052 cursor position.
1053 1053
1054 1054 Parameters
1055 1055 ----------
1056 1056 cursor_column : int
1057 1057 column position of the cursor in ``text``, 0-indexed.
1058 1058 cursor_line : int
1059 1059 line position of the cursor in ``text``, 0-indexed
1060 1060 text : str
1061 1061 text to complete
1062 1062
1063 1063 Debugging
1064 1064 ---------
1065 1065
1066 1066 If ``IPCompleter.debug`` is ``True`` may return a :any:`_FakeJediCompletion`
1067 1067 object containing a string with the Jedi debug information attached.
1068 1068 """
1069 1069 namespaces = [self.namespace]
1070 1070 if self.global_namespace is not None:
1071 1071 namespaces.append(self.global_namespace)
1072 1072
1073 1073 # cursor_pos is an it, jedi wants line and column
1074 1074 offset = cursor_to_position(text, cursor_line, cursor_column)
1075 1075 if offset:
1076 1076 pre = text[offset-1]
1077 1077 completion_filter = lambda x:x
1078 1078 if pre == '.':
1079 1079 if self.omit__names == 2:
1080 1080 completion_filter = lambda c:not c.name.startswith('_')
1081 1081 elif self.omit__names == 1:
1082 1082 completion_filter = lambda c:not (c.name.startswith('__') and c.name.endswith('__'))
1083 1083 elif self.omit__names == 0:
1084 1084 completion_filter = lambda x:x
1085 1085 else:
1086 1086 raise ValueError("Don't understand self.omit__names == {}".format(self.omit__names))
1087 1087
1088 1088 interpreter = jedi.Interpreter(
1089 1089 text, namespaces, column=cursor_column, line=cursor_line + 1)
1090 1090 try:
1091 1091 return filter(completion_filter, interpreter.completions())
1092 1092 except Exception as e:
1093 1093 if self.debug:
1094 1094 return [_FakeJediCompletion('Opps Jedi has crash please report a bug with the following:\n"""\n%s\ns"""' % (e))]
1095 1095 else:
1096 1096 return []
1097 1097
1098 1098 def python_matches(self, text):
1099 1099 """Match attributes or global python names"""
1100 1100 if "." in text:
1101 1101 try:
1102 1102 matches = self.attr_matches(text)
1103 1103 if text.endswith('.') and self.omit__names:
1104 1104 if self.omit__names == 1:
1105 1105 # true if txt is _not_ a __ name, false otherwise:
1106 1106 no__name = (lambda txt:
1107 1107 re.match(r'.*\.__.*?__',txt) is None)
1108 1108 else:
1109 1109 # true if txt is _not_ a _ name, false otherwise:
1110 1110 no__name = (lambda txt:
1111 1111 re.match(r'\._.*?',txt[txt.rindex('.'):]) is None)
1112 1112 matches = filter(no__name, matches)
1113 1113 except NameError:
1114 1114 # catches <undefined attributes>.<tab>
1115 1115 matches = []
1116 1116 else:
1117 1117 matches = self.global_matches(text)
1118 1118 return matches
1119 1119
1120 1120 def _default_arguments_from_docstring(self, doc):
1121 1121 """Parse the first line of docstring for call signature.
1122 1122
1123 1123 Docstring should be of the form 'min(iterable[, key=func])\n'.
1124 1124 It can also parse cython docstring of the form
1125 1125 'Minuit.migrad(self, int ncall=10000, resume=True, int nsplit=1)'.
1126 1126 """
1127 1127 if doc is None:
1128 1128 return []
1129 1129
1130 1130 #care only the firstline
1131 1131 line = doc.lstrip().splitlines()[0]
1132 1132
1133 1133 #p = re.compile(r'^[\w|\s.]+\(([^)]*)\).*')
1134 1134 #'min(iterable[, key=func])\n' -> 'iterable[, key=func]'
1135 1135 sig = self.docstring_sig_re.search(line)
1136 1136 if sig is None:
1137 1137 return []
1138 1138 # iterable[, key=func]' -> ['iterable[' ,' key=func]']
1139 1139 sig = sig.groups()[0].split(',')
1140 1140 ret = []
1141 1141 for s in sig:
1142 1142 #re.compile(r'[\s|\[]*(\w+)(?:\s*=\s*.*)')
1143 1143 ret += self.docstring_kwd_re.findall(s)
1144 1144 return ret
1145 1145
1146 1146 def _default_arguments(self, obj):
1147 1147 """Return the list of default arguments of obj if it is callable,
1148 1148 or empty list otherwise."""
1149 1149 call_obj = obj
1150 1150 ret = []
1151 1151 if inspect.isbuiltin(obj):
1152 1152 pass
1153 1153 elif not (inspect.isfunction(obj) or inspect.ismethod(obj)):
1154 1154 if inspect.isclass(obj):
1155 1155 #for cython embededsignature=True the constructor docstring
1156 1156 #belongs to the object itself not __init__
1157 1157 ret += self._default_arguments_from_docstring(
1158 1158 getattr(obj, '__doc__', ''))
1159 1159 # for classes, check for __init__,__new__
1160 1160 call_obj = (getattr(obj, '__init__', None) or
1161 1161 getattr(obj, '__new__', None))
1162 1162 # for all others, check if they are __call__able
1163 1163 elif hasattr(obj, '__call__'):
1164 1164 call_obj = obj.__call__
1165 1165 ret += self._default_arguments_from_docstring(
1166 1166 getattr(call_obj, '__doc__', ''))
1167 1167
1168 1168 _keeps = (inspect.Parameter.KEYWORD_ONLY,
1169 1169 inspect.Parameter.POSITIONAL_OR_KEYWORD)
1170 1170
1171 1171 try:
1172 1172 sig = inspect.signature(call_obj)
1173 1173 ret.extend(k for k, v in sig.parameters.items() if
1174 1174 v.kind in _keeps)
1175 1175 except ValueError:
1176 1176 pass
1177 1177
1178 1178 return list(set(ret))
1179 1179
1180 1180 def python_func_kw_matches(self,text):
1181 1181 """Match named parameters (kwargs) of the last open function"""
1182 1182
1183 1183 if "." in text: # a parameter cannot be dotted
1184 1184 return []
1185 1185 try: regexp = self.__funcParamsRegex
1186 1186 except AttributeError:
1187 1187 regexp = self.__funcParamsRegex = re.compile(r'''
1188 1188 '.*?(?<!\\)' | # single quoted strings or
1189 1189 ".*?(?<!\\)" | # double quoted strings or
1190 1190 \w+ | # identifier
1191 1191 \S # other characters
1192 1192 ''', re.VERBOSE | re.DOTALL)
1193 1193 # 1. find the nearest identifier that comes before an unclosed
1194 1194 # parenthesis before the cursor
1195 1195 # e.g. for "foo (1+bar(x), pa<cursor>,a=1)", the candidate is "foo"
1196 1196 tokens = regexp.findall(self.text_until_cursor)
1197 1197 iterTokens = reversed(tokens); openPar = 0
1198 1198
1199 1199 for token in iterTokens:
1200 1200 if token == ')':
1201 1201 openPar -= 1
1202 1202 elif token == '(':
1203 1203 openPar += 1
1204 1204 if openPar > 0:
1205 1205 # found the last unclosed parenthesis
1206 1206 break
1207 1207 else:
1208 1208 return []
1209 1209 # 2. Concatenate dotted names ("foo.bar" for "foo.bar(x, pa" )
1210 1210 ids = []
1211 1211 isId = re.compile(r'\w+$').match
1212 1212
1213 1213 while True:
1214 1214 try:
1215 1215 ids.append(next(iterTokens))
1216 1216 if not isId(ids[-1]):
1217 1217 ids.pop(); break
1218 1218 if not next(iterTokens) == '.':
1219 1219 break
1220 1220 except StopIteration:
1221 1221 break
1222 1222
1223 1223 # Find all named arguments already assigned to, as to avoid suggesting
1224 1224 # them again
1225 1225 usedNamedArgs = set()
1226 1226 par_level = -1
1227 1227 for token, next_token in zip(tokens, tokens[1:]):
1228 1228 if token == '(':
1229 1229 par_level += 1
1230 1230 elif token == ')':
1231 1231 par_level -= 1
1232 1232
1233 1233 if par_level != 0:
1234 1234 continue
1235 1235
1236 1236 if next_token != '=':
1237 1237 continue
1238 1238
1239 1239 usedNamedArgs.add(token)
1240 1240
1241 1241 # lookup the candidate callable matches either using global_matches
1242 1242 # or attr_matches for dotted names
1243 1243 if len(ids) == 1:
1244 1244 callableMatches = self.global_matches(ids[0])
1245 1245 else:
1246 1246 callableMatches = self.attr_matches('.'.join(ids[::-1]))
1247 1247 argMatches = []
1248 1248 for callableMatch in callableMatches:
1249 1249 try:
1250 1250 namedArgs = self._default_arguments(eval(callableMatch,
1251 1251 self.namespace))
1252 1252 except:
1253 1253 continue
1254 1254
1255 1255 # Remove used named arguments from the list, no need to show twice
1256 1256 for namedArg in set(namedArgs) - usedNamedArgs:
1257 1257 if namedArg.startswith(text):
1258 1258 argMatches.append(u"%s=" %namedArg)
1259 1259 return argMatches
1260 1260
1261 1261 def dict_key_matches(self, text):
1262 1262 "Match string keys in a dictionary, after e.g. 'foo[' "
1263 1263 def get_keys(obj):
1264 1264 # Objects can define their own completions by defining an
1265 1265 # _ipy_key_completions_() method.
1266 1266 method = get_real_method(obj, '_ipython_key_completions_')
1267 1267 if method is not None:
1268 1268 return method()
1269 1269
1270 1270 # Special case some common in-memory dict-like types
1271 1271 if isinstance(obj, dict) or\
1272 1272 _safe_isinstance(obj, 'pandas', 'DataFrame'):
1273 1273 try:
1274 1274 return list(obj.keys())
1275 1275 except Exception:
1276 1276 return []
1277 1277 elif _safe_isinstance(obj, 'numpy', 'ndarray') or\
1278 1278 _safe_isinstance(obj, 'numpy', 'void'):
1279 1279 return obj.dtype.names or []
1280 1280 return []
1281 1281
1282 1282 try:
1283 1283 regexps = self.__dict_key_regexps
1284 1284 except AttributeError:
1285 1285 dict_key_re_fmt = r'''(?x)
1286 1286 ( # match dict-referring expression wrt greedy setting
1287 1287 %s
1288 1288 )
1289 1289 \[ # open bracket
1290 1290 \s* # and optional whitespace
1291 1291 ([uUbB]? # string prefix (r not handled)
1292 1292 (?: # unclosed string
1293 1293 '(?:[^']|(?<!\\)\\')*
1294 1294 |
1295 1295 "(?:[^"]|(?<!\\)\\")*
1296 1296 )
1297 1297 )?
1298 1298 $
1299 1299 '''
1300 1300 regexps = self.__dict_key_regexps = {
1301 1301 False: re.compile(dict_key_re_fmt % '''
1302 1302 # identifiers separated by .
1303 1303 (?!\d)\w+
1304 1304 (?:\.(?!\d)\w+)*
1305 1305 '''),
1306 1306 True: re.compile(dict_key_re_fmt % '''
1307 1307 .+
1308 1308 ''')
1309 1309 }
1310 1310
1311 1311 match = regexps[self.greedy].search(self.text_until_cursor)
1312 1312 if match is None:
1313 1313 return []
1314 1314
1315 1315 expr, prefix = match.groups()
1316 1316 try:
1317 1317 obj = eval(expr, self.namespace)
1318 1318 except Exception:
1319 1319 try:
1320 1320 obj = eval(expr, self.global_namespace)
1321 1321 except Exception:
1322 1322 return []
1323 1323
1324 1324 keys = get_keys(obj)
1325 1325 if not keys:
1326 1326 return keys
1327 1327 closing_quote, token_offset, matches = match_dict_keys(keys, prefix, self.splitter.delims)
1328 1328 if not matches:
1329 1329 return matches
1330 1330
1331 1331 # get the cursor position of
1332 1332 # - the text being completed
1333 1333 # - the start of the key text
1334 1334 # - the start of the completion
1335 1335 text_start = len(self.text_until_cursor) - len(text)
1336 1336 if prefix:
1337 1337 key_start = match.start(2)
1338 1338 completion_start = key_start + token_offset
1339 1339 else:
1340 1340 key_start = completion_start = match.end()
1341 1341
1342 1342 # grab the leading prefix, to make sure all completions start with `text`
1343 1343 if text_start > key_start:
1344 1344 leading = ''
1345 1345 else:
1346 1346 leading = text[text_start:completion_start]
1347 1347
1348 1348 # the index of the `[` character
1349 1349 bracket_idx = match.end(1)
1350 1350
1351 1351 # append closing quote and bracket as appropriate
1352 1352 # this is *not* appropriate if the opening quote or bracket is outside
1353 1353 # the text given to this method
1354 1354 suf = ''
1355 1355 continuation = self.line_buffer[len(self.text_until_cursor):]
1356 1356 if key_start > text_start and closing_quote:
1357 1357 # quotes were opened inside text, maybe close them
1358 1358 if continuation.startswith(closing_quote):
1359 1359 continuation = continuation[len(closing_quote):]
1360 1360 else:
1361 1361 suf += closing_quote
1362 1362 if bracket_idx > text_start:
1363 1363 # brackets were opened inside text, maybe close them
1364 1364 if not continuation.startswith(']'):
1365 1365 suf += ']'
1366 1366
1367 1367 return [leading + k + suf for k in matches]
1368 1368
1369 1369 def unicode_name_matches(self, text):
1370 1370 u"""Match Latex-like syntax for unicode characters base
1371 1371 on the name of the character.
1372 1372
1373 1373 This does ``\\GREEK SMALL LETTER ETA`` -> ``Ξ·``
1374 1374
1375 1375 Works only on valid python 3 identifier, or on combining characters that
1376 1376 will combine to form a valid identifier.
1377 1377
1378 1378 Used on Python 3 only.
1379 1379 """
1380 1380 slashpos = text.rfind('\\')
1381 1381 if slashpos > -1:
1382 1382 s = text[slashpos+1:]
1383 1383 try :
1384 1384 unic = unicodedata.lookup(s)
1385 1385 # allow combining chars
1386 1386 if ('a'+unic).isidentifier():
1387 1387 return '\\'+s,[unic]
1388 1388 except KeyError:
1389 1389 pass
1390 1390 return u'', []
1391 1391
1392 1392
1393 1393 def latex_matches(self, text):
1394 1394 u"""Match Latex syntax for unicode characters.
1395 1395
1396 1396 This does both ``\\alp`` -> ``\\alpha`` and ``\\alpha`` -> ``Ξ±``
1397 1397
1398 1398 Used on Python 3 only.
1399 1399 """
1400 1400 slashpos = text.rfind('\\')
1401 1401 if slashpos > -1:
1402 1402 s = text[slashpos:]
1403 1403 if s in latex_symbols:
1404 1404 # Try to complete a full latex symbol to unicode
1405 1405 # \\alpha -> Ξ±
1406 1406 return s, [latex_symbols[s]]
1407 1407 else:
1408 1408 # If a user has partially typed a latex symbol, give them
1409 1409 # a full list of options \al -> [\aleph, \alpha]
1410 1410 matches = [k for k in latex_symbols if k.startswith(s)]
1411 1411 return s, matches
1412 1412 return u'', []
1413 1413
1414 1414 def dispatch_custom_completer(self, text):
1415 1415 if not self.custom_completers:
1416 1416 return
1417 1417
1418 1418 line = self.line_buffer
1419 1419 if not line.strip():
1420 1420 return None
1421 1421
1422 1422 # Create a little structure to pass all the relevant information about
1423 1423 # the current completion to any custom completer.
1424 1424 event = SimpleNamespace()
1425 1425 event.line = line
1426 1426 event.symbol = text
1427 1427 cmd = line.split(None,1)[0]
1428 1428 event.command = cmd
1429 1429 event.text_until_cursor = self.text_until_cursor
1430 1430
1431 1431 # for foo etc, try also to find completer for %foo
1432 1432 if not cmd.startswith(self.magic_escape):
1433 1433 try_magic = self.custom_completers.s_matches(
1434 1434 self.magic_escape + cmd)
1435 1435 else:
1436 1436 try_magic = []
1437 1437
1438 1438 for c in itertools.chain(self.custom_completers.s_matches(cmd),
1439 1439 try_magic,
1440 1440 self.custom_completers.flat_matches(self.text_until_cursor)):
1441 1441 try:
1442 1442 res = c(event)
1443 1443 if res:
1444 1444 # first, try case sensitive match
1445 1445 withcase = [cast_unicode_py2(r) for r in res if r.startswith(text)]
1446 1446 if withcase:
1447 1447 return withcase
1448 1448 # if none, then case insensitive ones are ok too
1449 1449 text_low = text.lower()
1450 1450 return [cast_unicode_py2(r) for r in res if r.lower().startswith(text_low)]
1451 1451 except TryNext:
1452 1452 pass
1453 1453
1454 1454 return None
1455 1455
1456 1456 def completions(self, text: str, offset: int)->Iterator[Completion]:
1457 1457 """
1458 1458 Returns an iterator over the possible completions
1459 1459
1460 1460 .. warning:: Unstable
1461 1461
1462 1462 This function is unstable, API may change without warning.
1463 1463 It will also raise unless use in proper context manager.
1464 1464
1465 1465 Parameters
1466 1466 ----------
1467 1467
1468 1468 text:str
1469 1469 Full text of the current input, multi line string.
1470 1470 offset:int
1471 1471 Integer representing the position of the cursor in ``text``. Offset
1472 1472 is 0-based indexed.
1473 1473
1474 1474 Yields
1475 1475 ------
1476 1476 :any:`Completion` object
1477 1477
1478 1478
1479 1479 The cursor on a text can either be seen as being "in between"
1480 1480 characters or "On" a character depending on the interface visible to
1481 1481 the user. For consistency the cursor being on "in between" characters X
1482 1482 and Y is equivalent to the cursor being "on" character Y, that is to say
1483 1483 the character the cursor is on is considered as being after the cursor.
1484 1484
1485 1485 Combining characters may span more that one position in the
1486 1486 text.
1487 1487
1488 1488
1489 1489 .. note::
1490 1490
1491 1491 If ``IPCompleter.debug`` is :any:`True` will yield a ``--jedi/ipython--``
1492 1492 fake Completion token to distinguish completion returned by Jedi
1493 1493 and usual IPython completion.
1494 1494
1495 1495 """
1496 1496 warnings.warn("_complete is a provisional API (as of IPython 6.0). "
1497 1497 "It may change without warnings. "
1498 1498 "Use in corresponding context manager.",
1499 1499 category=ProvisionalCompleterWarning, stacklevel=2)
1500 1500
1501 1501 # Possible Improvements / Known limitation
1502 1502 ##########################################
1503 1503 # Completions may be identical even if they have different ranges and
1504 1504 # text. For example:
1505 1505 # >>> a=1
1506 1506 # >>> a.<tab>
1507 1507 # May returns:
1508 1508 # - `a.real` from 0 to 2
1509 1509 # - `.real` from 1 to 2
1510 1510 # the current code does not (yet) check for such equivalence
1511 1511 seen = set()
1512 1512 for c in self._completions(text, offset, _timeout=self.jedi_compute_type_timeout/1000):
1513 1513 if c and (c in seen):
1514 1514 continue
1515 1515 yield c
1516 1516 seen.add(c)
1517 1517
1518 1518 def _completions(self, full_text: str, offset: int, *, _timeout)->Iterator[Completion]:
1519 1519 """
1520 1520 Core completion module.Same signature as :any:`completions`, with the
1521 1521 extra `timeout` parameter (in seconds).
1522 1522
1523 1523
1524 1524 Computing jedi's completion ``.type`` can be quite expensive (it is a
1525 1525 lazy property) and can require some warm-up, more warm up than just
1526 1526 computing the ``name`` of a completion. The warm-up can be :
1527 1527
1528 1528 - Long warm-up the fisrt time a module is encountered after
1529 1529 install/update: actually build parse/inference tree.
1530 1530
1531 1531 - first time the module is encountered in a session: load tree from
1532 1532 disk.
1533 1533
1534 1534 We don't want to block completions for tens of seconds so we give the
1535 1535 completer a "budget" of ``_timeout`` seconds per invocation to compute
1536 1536 completions types, the completions that have not yet been computed will
1537 1537 be marked as "unknown" an will have a chance to be computed next round
1538 1538 are things get cached.
1539 1539
1540 1540 Keep in mind that Jedi is not the only thing treating the completion so
1541 1541 keep the timeout short-ish as if we take more than 0.3 second we still
1542 1542 have lots of processing to do.
1543 1543
1544 1544 """
1545 1545 deadline = time.monotonic() + _timeout
1546 1546
1547 1547
1548 1548 before = full_text[:offset]
1549 1549 cursor_line, cursor_column = position_to_cursor(full_text, offset)
1550 1550
1551 1551 matched_text, matches, matches_origin, jedi_matches = self._complete(
1552 1552 full_text=full_text, cursor_line=cursor_line, cursor_pos=cursor_column)
1553 1553
1554 1554 iter_jm = iter(jedi_matches)
1555 1555 if _timeout:
1556 1556 for jm in iter_jm:
1557 try:
1558 type_ = jm.type
1559 except Exception:
1560 if self.debug:
1561 print("Error in Jedi getting type of ", jm)
1562 type_ = None
1557 1563 delta = len(jm.name_with_symbols) - len(jm.complete)
1558 1564 yield Completion(start=offset - delta,
1559 1565 end=offset,
1560 1566 text=jm.name_with_symbols,
1561 type=jm.type,
1567 type=type_,
1562 1568 _origin='jedi')
1563 1569
1564 1570 if time.monotonic() > deadline:
1565 1571 break
1566 1572
1567 1573 for jm in iter_jm:
1568 1574 delta = len(jm.name_with_symbols) - len(jm.complete)
1569 1575 yield Completion(start=offset - delta,
1570 1576 end=offset,
1571 1577 text=jm.name_with_symbols,
1572 1578 type='<unknown>', # don't compute type for speed
1573 1579 _origin='jedi')
1574 1580
1575 1581
1576 1582 start_offset = before.rfind(matched_text)
1577 1583
1578 1584 # TODO:
1579 1585 # Supress this, right now just for debug.
1580 1586 if jedi_matches and matches and self.debug:
1581 1587 yield Completion(start=start_offset, end=offset, text='--jedi/ipython--', _origin='debug')
1582 1588
1583 1589 # I'm unsure if this is always true, so let's assert and see if it
1584 1590 # crash
1585 1591 assert before.endswith(matched_text)
1586 1592 for m, t in zip(matches, matches_origin):
1587 1593 yield Completion(start=start_offset, end=offset, text=m, _origin=t)
1588 1594
1589 1595
1590 1596 def complete(self, text=None, line_buffer=None, cursor_pos=None):
1591 1597 """Find completions for the given text and line context.
1592 1598
1593 1599 Note that both the text and the line_buffer are optional, but at least
1594 1600 one of them must be given.
1595 1601
1596 1602 Parameters
1597 1603 ----------
1598 1604 text : string, optional
1599 1605 Text to perform the completion on. If not given, the line buffer
1600 1606 is split using the instance's CompletionSplitter object.
1601 1607
1602 1608 line_buffer : string, optional
1603 1609 If not given, the completer attempts to obtain the current line
1604 1610 buffer via readline. This keyword allows clients which are
1605 1611 requesting for text completions in non-readline contexts to inform
1606 1612 the completer of the entire text.
1607 1613
1608 1614 cursor_pos : int, optional
1609 1615 Index of the cursor in the full line buffer. Should be provided by
1610 1616 remote frontends where kernel has no access to frontend state.
1611 1617
1612 1618 Returns
1613 1619 -------
1614 1620 text : str
1615 1621 Text that was actually used in the completion.
1616 1622
1617 1623 matches : list
1618 1624 A list of completion matches.
1619 1625
1620 1626
1621 1627 .. note::
1622 1628
1623 1629 This API is likely to be deprecated and replaced by
1624 1630 :any:`IPCompleter.completions` in the future.
1625 1631
1626 1632
1627 1633 """
1628 1634 warnings.warn('`Completer.complete` is pending deprecation since '
1629 1635 'IPython 6.0 and will be replaced by `Completer.completions`.',
1630 1636 PendingDeprecationWarning)
1631 1637 # potential todo, FOLD the 3rd throw away argument of _complete
1632 1638 # into the first 2 one.
1633 1639 return self._complete(line_buffer=line_buffer, cursor_pos=cursor_pos, text=text, cursor_line=0)[:2]
1634 1640
1635 1641 def _complete(self, *, cursor_line, cursor_pos, line_buffer=None, text=None,
1636 1642 full_text=None, return_jedi_results=True) -> (str, List[str], List[object]):
1637 1643 """
1638 1644
1639 1645 Like complete but can also returns raw jedi completions as well as the
1640 1646 origin of the completion text. This could (and should) be made much
1641 1647 cleaner but that will be simpler once we drop the old (and stateful)
1642 1648 :any:`complete` API.
1643 1649
1644 1650
1645 1651 With current provisional API, cursor_pos act both (depending on the
1646 1652 caller) as the offset in the ``text`` or ``line_buffer``, or as the
1647 1653 ``column`` when passing multiline strings this could/should be renamed
1648 1654 but would add extra noise.
1649 1655 """
1650 1656
1651 1657 # if the cursor position isn't given, the only sane assumption we can
1652 1658 # make is that it's at the end of the line (the common case)
1653 1659 if cursor_pos is None:
1654 1660 cursor_pos = len(line_buffer) if text is None else len(text)
1655 1661
1656 1662 if self.use_main_ns:
1657 1663 self.namespace = __main__.__dict__
1658 1664
1659 1665 # if text is either None or an empty string, rely on the line buffer
1660 1666 if (not line_buffer) and full_text:
1661 1667 line_buffer = full_text.split('\n')[cursor_line]
1662 1668 if not text:
1663 1669 text = self.splitter.split_line(line_buffer, cursor_pos)
1664 1670
1665 1671 base_text = text if not line_buffer else line_buffer[:cursor_pos]
1666 1672 latex_text, latex_matches = self.latex_matches(base_text)
1667 1673 if latex_matches:
1668 1674 return latex_text, latex_matches, ['latex_matches']*len(latex_matches), ()
1669 1675 name_text = ''
1670 1676 name_matches = []
1671 1677 for meth in (self.unicode_name_matches, back_latex_name_matches, back_unicode_name_matches):
1672 1678 name_text, name_matches = meth(base_text)
1673 1679 if name_text:
1674 1680 return name_text, name_matches, [meth.__qualname__]*len(name_matches), {}
1675 1681
1676 1682
1677 1683 # If no line buffer is given, assume the input text is all there was
1678 1684 if line_buffer is None:
1679 1685 line_buffer = text
1680 1686
1681 1687 self.line_buffer = line_buffer
1682 1688 self.text_until_cursor = self.line_buffer[:cursor_pos]
1683 1689
1684 1690 # Start with a clean slate of completions
1685 1691 matches = []
1686 1692 custom_res = self.dispatch_custom_completer(text)
1687 1693 # FIXME: we should extend our api to return a dict with completions for
1688 1694 # different types of objects. The rlcomplete() method could then
1689 1695 # simply collapse the dict into a list for readline, but we'd have
1690 1696 # richer completion semantics in other evironments.
1691 1697 completions = ()
1692 1698 if self.use_jedi and return_jedi_results:
1693 1699 if not full_text:
1694 1700 full_text = line_buffer
1695 1701 completions = self._jedi_matches(
1696 1702 cursor_pos, cursor_line, full_text)
1697 1703 if custom_res is not None:
1698 1704 # did custom completers produce something?
1699 1705 matches = [(m, 'custom') for m in custom_res]
1700 1706 else:
1701 1707 # Extend the list of completions with the results of each
1702 1708 # matcher, so we return results to the user from all
1703 1709 # namespaces.
1704 1710 if self.merge_completions:
1705 1711 matches = []
1706 1712 for matcher in self.matchers:
1707 1713 try:
1708 1714 matches.extend([(m, matcher.__qualname__)
1709 1715 for m in matcher(text)])
1710 1716 except:
1711 1717 # Show the ugly traceback if the matcher causes an
1712 1718 # exception, but do NOT crash the kernel!
1713 1719 sys.excepthook(*sys.exc_info())
1714 1720 else:
1715 1721 for matcher in self.matchers:
1716 1722 matches = [(m, matcher.__qualname__)
1717 1723 for m in matcher(text)]
1718 1724 if matches:
1719 1725 break
1720 1726 seen = set()
1721 1727 filtered_matches = set()
1722 1728 for m in matches:
1723 1729 t, c = m
1724 1730 if t not in seen:
1725 1731 filtered_matches.add(m)
1726 1732 seen.add(t)
1727 1733
1728 1734 filtered_matches = sorted(
1729 1735 set(filtered_matches), key=lambda x: completions_sorting_key(x[0]))
1730 1736
1731 1737 matches = [m[0] for m in filtered_matches]
1732 1738 origins = [m[1] for m in filtered_matches]
1733 1739
1734 1740 self.matches = matches
1735 1741
1736 1742 return text, matches, origins, completions
General Comments 0
You need to be logged in to leave comments. Login now