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