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