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