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