##// END OF EJS Templates
Merge pull request #10263 from Carreau/fix-bytes-completion...
Thomas Kluyver -
r23325:1076c0db merge
parent child Browse files
Show More
@@ -1,1742 +1,1760 b''
1 1 # encoding: utf-8
2 2 """Completion for IPython.
3 3
4 4 This module started as fork of the rlcompleter module in the Python standard
5 5 library. The original enhancements made to rlcompleter have been sent
6 6 upstream and were accepted as of Python 2.3,
7 7
8 8 This module now support a wide variety of completion mechanism both available
9 9 for normal classic Python code, as well as completer for IPython specific
10 10 Syntax like magics.
11 11
12 12 Experimental
13 13 ============
14 14
15 15 Starting with IPython 6.0, this module can make use of the Jedi library to
16 16 generate completions both using static analysis of the code, and dynamically
17 17 inspecting multiple namespaces. The APIs attached to this new mechanism is
18 18 unstable and will raise unless use in an :any:`provisionalcompleter` context
19 19 manager.
20 20
21 21 You will find that the following are experimental:
22 22
23 23 - :any:`provisionalcompleter`
24 24 - :any:`IPCompleter.completions`
25 25 - :any:`Completion`
26 26 - :any:`rectify_completions`
27 27
28 28 .. note::
29 29
30 30 better name for :any:`rectify_completions` ?
31 31
32 32 We welcome any feedback on these new API, and we also encourage you to try this
33 33 module in debug mode (start IPython with ``--Completer.debug=True``) in order
34 34 to have extra logging information is :any:`jedi` is crashing, or if current
35 35 IPython completer pending deprecations are returning results not yet handled
36 36 by :any:`jedi`.
37 37
38 38 Using Jedi for tab completion allow snippets like the following to work without
39 39 having to execute any code:
40 40
41 41 >>> myvar = ['hello', 42]
42 42 ... myvar[1].bi<tab>
43 43
44 44 Tab completion will be able to infer that ``myvar[1]`` is a real number without
45 45 executing any code unlike the previously available ``IPCompleter.greedy``
46 46 option.
47 47
48 48 Be sure to update :any:`jedi` to the latest stable version or to try the
49 49 current development version to get better completions.
50 50 """
51 51
52 52 # skip module docstests
53 53 skip_doctest = True
54 54
55 55 # Copyright (c) IPython Development Team.
56 56 # Distributed under the terms of the Modified BSD License.
57 57 #
58 58 # Some of this code originated from rlcompleter in the Python standard library
59 59 # Copyright (C) 2001 Python Software Foundation, www.python.org
60 60
61 61
62 62 import __main__
63 63 import builtins as builtin_mod
64 64 import glob
65 65 import time
66 66 import inspect
67 67 import itertools
68 68 import keyword
69 69 import os
70 70 import re
71 71 import sys
72 72 import unicodedata
73 73 import string
74 74 import warnings
75 75
76 76 from contextlib import contextmanager
77 77 from importlib import import_module
78 78 from typing import Iterator, List
79 79 from types import SimpleNamespace
80 80
81 81 from traitlets.config.configurable import Configurable
82 82 from IPython.core.error import TryNext
83 83 from IPython.core.inputsplitter import ESC_MAGIC
84 84 from IPython.core.latex_symbols import latex_symbols, reverse_latex_symbol
85 85 from IPython.utils import generics
86 86 from IPython.utils.dir2 import dir2, get_real_method
87 87 from IPython.utils.process import arg_split
88 88 from IPython.utils.py3compat import cast_unicode_py2
89 89 from traitlets import Bool, Enum, observe, Int
90 90
91 91 try:
92 92 import jedi
93 93 import jedi.api.helpers
94 94 JEDI_INSTALLED = True
95 95 except ImportError:
96 96 JEDI_INSTALLED = False
97 97 #-----------------------------------------------------------------------------
98 98 # Globals
99 99 #-----------------------------------------------------------------------------
100 100
101 101 # Public API
102 102 __all__ = ['Completer','IPCompleter']
103 103
104 104 if sys.platform == 'win32':
105 105 PROTECTABLES = ' '
106 106 else:
107 107 PROTECTABLES = ' ()[]{}?=\\|;:\'#*"^&'
108 108
109 109
110 110 _deprecation_readline_sentinel = object()
111 111
112 112
113 113 class ProvisionalCompleterWarning(FutureWarning):
114 114 """
115 115 Exception raise by an experimental feature in this module.
116 116
117 117 Wrap code in :any:`provisionalcompleter` context manager if you
118 118 are certain you want to use an unstable feature.
119 119 """
120 120 pass
121 121
122 122 warnings.filterwarnings('error', category=ProvisionalCompleterWarning)
123 123
124 124 @contextmanager
125 125 def provisionalcompleter(action='ignore'):
126 126 """
127 127
128 128
129 129 This contest manager has to be used in any place where unstable completer
130 130 behavior and API may be called.
131 131
132 132 >>> with provisionalcompleter():
133 133 ... completer.do_experimetal_things() # works
134 134
135 135 >>> completer.do_experimental_things() # raises.
136 136
137 137 .. note:: Unstable
138 138
139 139 By using this context manager you agree that the API in use may change
140 140 without warning, and that you won't complain if they do so.
141 141
142 142 You also understand that if the API is not to you liking you should report
143 143 a bug to explain your use case upstream and improve the API and will loose
144 144 credibility if you complain after the API is make stable.
145 145
146 146 We'll be happy to get your feedback , feature request and improvement on
147 147 any of the unstable APIs !
148 148 """
149 149 with warnings.catch_warnings():
150 150 warnings.filterwarnings(action, category=ProvisionalCompleterWarning)
151 151 yield
152 152
153 153
154 154 def has_open_quotes(s):
155 155 """Return whether a string has open quotes.
156 156
157 157 This simply counts whether the number of quote characters of either type in
158 158 the string is odd.
159 159
160 160 Returns
161 161 -------
162 162 If there is an open quote, the quote character is returned. Else, return
163 163 False.
164 164 """
165 165 # We check " first, then ', so complex cases with nested quotes will get
166 166 # the " to take precedence.
167 167 if s.count('"') % 2:
168 168 return '"'
169 169 elif s.count("'") % 2:
170 170 return "'"
171 171 else:
172 172 return False
173 173
174 174
175 175 def protect_filename(s):
176 176 """Escape a string to protect certain characters."""
177 177 if set(s) & set(PROTECTABLES):
178 178 if sys.platform == "win32":
179 179 return '"' + s + '"'
180 180 else:
181 181 return "".join(("\\" + c if c in PROTECTABLES else c) for c in s)
182 182 else:
183 183 return s
184 184
185 185
186 186 def expand_user(path):
187 187 """Expand ``~``-style usernames in strings.
188 188
189 189 This is similar to :func:`os.path.expanduser`, but it computes and returns
190 190 extra information that will be useful if the input was being used in
191 191 computing completions, and you wish to return the completions with the
192 192 original '~' instead of its expanded value.
193 193
194 194 Parameters
195 195 ----------
196 196 path : str
197 197 String to be expanded. If no ~ is present, the output is the same as the
198 198 input.
199 199
200 200 Returns
201 201 -------
202 202 newpath : str
203 203 Result of ~ expansion in the input path.
204 204 tilde_expand : bool
205 205 Whether any expansion was performed or not.
206 206 tilde_val : str
207 207 The value that ~ was replaced with.
208 208 """
209 209 # Default values
210 210 tilde_expand = False
211 211 tilde_val = ''
212 212 newpath = path
213 213
214 214 if path.startswith('~'):
215 215 tilde_expand = True
216 216 rest = len(path)-1
217 217 newpath = os.path.expanduser(path)
218 218 if rest:
219 219 tilde_val = newpath[:-rest]
220 220 else:
221 221 tilde_val = newpath
222 222
223 223 return newpath, tilde_expand, tilde_val
224 224
225 225
226 226 def compress_user(path, tilde_expand, tilde_val):
227 227 """Does the opposite of expand_user, with its outputs.
228 228 """
229 229 if tilde_expand:
230 230 return path.replace(tilde_val, '~')
231 231 else:
232 232 return path
233 233
234 234
235 235 def completions_sorting_key(word):
236 236 """key for sorting completions
237 237
238 238 This does several things:
239 239
240 240 - Lowercase all completions, so they are sorted alphabetically with
241 241 upper and lower case words mingled
242 242 - Demote any completions starting with underscores to the end
243 243 - Insert any %magic and %%cellmagic completions in the alphabetical order
244 244 by their name
245 245 """
246 246 # Case insensitive sort
247 247 word = word.lower()
248 248
249 249 prio1, prio2 = 0, 0
250 250
251 251 if word.startswith('__'):
252 252 prio1 = 2
253 253 elif word.startswith('_'):
254 254 prio1 = 1
255 255
256 256 if word.endswith('='):
257 257 prio1 = -1
258 258
259 259 if word.startswith('%%'):
260 260 # If there's another % in there, this is something else, so leave it alone
261 261 if not "%" in word[2:]:
262 262 word = word[2:]
263 263 prio2 = 2
264 264 elif word.startswith('%'):
265 265 if not "%" in word[1:]:
266 266 word = word[1:]
267 267 prio2 = 1
268 268
269 269 return prio1, word, prio2
270 270
271 271
272 272 class _FakeJediCompletion:
273 273 """
274 274 This is a workaround to communicate to the UI that Jedi has crashed and to
275 275 report a bug. Will be used only id :any:`IPCompleter.debug` is set to true.
276 276
277 277 Added in IPython 6.0 so should likely be removed for 7.0
278 278
279 279 """
280 280
281 281 def __init__(self, name):
282 282
283 283 self.name = name
284 284 self.complete = name
285 285 self.type = 'crashed'
286 286 self.name_with_symbols = name
287 287
288 288 def __repr__(self):
289 289 return '<Fake completion object jedi has crashed>'
290 290
291 291
292 292 class Completion:
293 293 """
294 294 Completion object used and return by IPython completers.
295 295
296 296 .. warning:: Unstable
297 297
298 298 This function is unstable, API may change without warning.
299 299 It will also raise unless use in proper context manager.
300 300
301 301 This act as a middle ground :any:`Completion` object between the
302 302 :any:`jedi.api.classes.Completion` object and the Prompt Toolkit completion
303 303 object. While Jedi need a lot of information about evaluator and how the
304 304 code should be ran/inspected, PromptToolkit (and other frontend) mostly
305 305 need user facing information.
306 306
307 307 - Which range should be replaced replaced by what.
308 308 - Some metadata (like completion type), or meta informations to displayed to
309 309 the use user.
310 310
311 311 For debugging purpose we can also store the origin of the completion (``jedi``,
312 312 ``IPython.python_matches``, ``IPython.magics_matches``...).
313 313 """
314 314
315 315 def __init__(self, start: int, end: int, text: str, *, type: str=None, _origin=''):
316 316 warnings.warn("``Completion`` is a provisional API (as of IPython 6.0). "
317 317 "It may change without warnings. "
318 318 "Use in corresponding context manager.",
319 319 category=ProvisionalCompleterWarning, stacklevel=2)
320 320
321 321 self.start = start
322 322 self.end = end
323 323 self.text = text
324 324 self.type = type
325 325 self._origin = _origin
326 326
327 327 def __repr__(self):
328 328 return '<Completion start=%s end=%s text=%r type=%r>' % (self.start, self.end, self.text, self.type or '?')
329 329
330 330 def __eq__(self, other)->Bool:
331 331 """
332 332 Equality and hash do not hash the type (as some completer may not be
333 333 able to infer the type), but are use to (partially) de-duplicate
334 334 completion.
335 335
336 336 Completely de-duplicating completion is a bit tricker that just
337 337 comparing as it depends on surrounding text, which Completions are not
338 338 aware of.
339 339 """
340 340 return self.start == other.start and \
341 341 self.end == other.end and \
342 342 self.text == other.text
343 343
344 344 def __hash__(self):
345 345 return hash((self.start, self.end, self.text))
346 346
347 347 _IC = Iterator[Completion]
348 348
349 349 def rectify_completions(text:str, completion:_IC, *, _debug=False)->_IC:
350 350 """
351 351 Rectify a set of completion to all have the same ``start`` and ``end``
352 352
353 353 .. warning:: Unstable
354 354
355 355 This function is unstable, API may change without warning.
356 356 It will also raise unless use in proper context manager.
357 357
358 358 Parameters
359 359 ----------
360 360 text: str
361 361 text that should be completed.
362 362 completion: Iterator[Completion]
363 363 iterator over the completions to rectify
364 364
365 365
366 366 :any:`jedi.api.classes.Completion` s returned by Jedi may not have the same start and end, though
367 367 the Jupyter Protocol requires them to behave like so. This will readjust
368 368 the completion to have the same ``start`` and ``end` by padding both
369 369 extremities with surrounding text.
370 370
371 371 During stabilisation should support a ``_debug`` option to log which
372 372 completion are return by the IPython completer and not found in Jedi in
373 373 order to make upstream bug report.
374 374 """
375 375 warnings.warn("`rectify_completions` is a provisional API (as of IPython 6.0). "
376 376 "It may change without warnings. "
377 377 "Use in corresponding context manager.",
378 378 category=ProvisionalCompleterWarning, stacklevel=2)
379 379
380 380 completions = list(completion)
381 381 if not completions:
382 382 return
383 383 starts = (c.start for c in completions)
384 384 ends = (c.end for c in completions)
385 385
386 386 new_start = min(starts)
387 387 new_end = max(ends)
388 388
389 389 seen_jedi = set()
390 390 seen_python_matches = set()
391 391 for c in completions:
392 392 new_text = text[new_start:c.start] + c.text + text[c.end:new_end]
393 393 if c._origin == 'jedi':
394 394 seen_jedi.add(new_text)
395 395 elif c._origin == 'IPCompleter.python_matches':
396 396 seen_python_matches.add(new_text)
397 397 yield Completion(new_start, new_end, new_text, type=c.type, _origin=c._origin)
398 398 diff = seen_python_matches.difference(seen_jedi)
399 399 if diff and _debug:
400 400 print('IPython.python matches have extras:', diff)
401 401
402 402
403 403 if sys.platform == 'win32':
404 404 DELIMS = ' \t\n`!@#$^&*()=+[{]}|;\'",<>?'
405 405 else:
406 406 DELIMS = ' \t\n`!@#$^&*()=+[{]}\\|;:\'",<>?'
407 407
408 408 GREEDY_DELIMS = ' =\r\n'
409 409
410 410
411 411 class CompletionSplitter(object):
412 412 """An object to split an input line in a manner similar to readline.
413 413
414 414 By having our own implementation, we can expose readline-like completion in
415 415 a uniform manner to all frontends. This object only needs to be given the
416 416 line of text to be split and the cursor position on said line, and it
417 417 returns the 'word' to be completed on at the cursor after splitting the
418 418 entire line.
419 419
420 420 What characters are used as splitting delimiters can be controlled by
421 421 setting the ``delims`` attribute (this is a property that internally
422 422 automatically builds the necessary regular expression)"""
423 423
424 424 # Private interface
425 425
426 426 # A string of delimiter characters. The default value makes sense for
427 427 # IPython's most typical usage patterns.
428 428 _delims = DELIMS
429 429
430 430 # The expression (a normal string) to be compiled into a regular expression
431 431 # for actual splitting. We store it as an attribute mostly for ease of
432 432 # debugging, since this type of code can be so tricky to debug.
433 433 _delim_expr = None
434 434
435 435 # The regular expression that does the actual splitting
436 436 _delim_re = None
437 437
438 438 def __init__(self, delims=None):
439 439 delims = CompletionSplitter._delims if delims is None else delims
440 440 self.delims = delims
441 441
442 442 @property
443 443 def delims(self):
444 444 """Return the string of delimiter characters."""
445 445 return self._delims
446 446
447 447 @delims.setter
448 448 def delims(self, delims):
449 449 """Set the delimiters for line splitting."""
450 450 expr = '[' + ''.join('\\'+ c for c in delims) + ']'
451 451 self._delim_re = re.compile(expr)
452 452 self._delims = delims
453 453 self._delim_expr = expr
454 454
455 455 def split_line(self, line, cursor_pos=None):
456 456 """Split a line of text with a cursor at the given position.
457 457 """
458 458 l = line if cursor_pos is None else line[:cursor_pos]
459 459 return self._delim_re.split(l)[-1]
460 460
461 461
462 462
463 463 class Completer(Configurable):
464 464
465 465 greedy = Bool(False,
466 466 help="""Activate greedy completion
467 467 PENDING DEPRECTION. this is now mostly taken care of with Jedi.
468 468
469 469 This will enable completion on elements of lists, results of function calls, etc.,
470 470 but can be unsafe because the code is actually evaluated on TAB.
471 471 """
472 472 ).tag(config=True)
473 473
474 474 use_jedi = Bool(default_value=JEDI_INSTALLED,
475 475 help="Experimental: Use Jedi to generate autocompletions. "
476 476 "Default to True if jedi is installed").tag(config=True)
477 477
478 478 jedi_compute_type_timeout = Int(default_value=400,
479 479 help="""Experimental: restrict time (in milliseconds) during which Jedi can compute types.
480 480 Set to 0 to stop computing types. Non-zero value lower than 100ms may hurt
481 481 performance by preventing jedi to build its cache.
482 482 """).tag(config=True)
483 483
484 484 debug = Bool(default_value=False,
485 485 help='Enable debug for the Completer. Mostly print extra '
486 486 'information for experimental jedi integration.')\
487 487 .tag(config=True)
488 488
489 489
490 490 def __init__(self, namespace=None, global_namespace=None, **kwargs):
491 491 """Create a new completer for the command line.
492 492
493 493 Completer(namespace=ns, global_namespace=ns2) -> completer instance.
494 494
495 495 If unspecified, the default namespace where completions are performed
496 496 is __main__ (technically, __main__.__dict__). Namespaces should be
497 497 given as dictionaries.
498 498
499 499 An optional second namespace can be given. This allows the completer
500 500 to handle cases where both the local and global scopes need to be
501 501 distinguished.
502 502 """
503 503
504 504 # Don't bind to namespace quite yet, but flag whether the user wants a
505 505 # specific namespace or to use __main__.__dict__. This will allow us
506 506 # to bind to __main__.__dict__ at completion time, not now.
507 507 if namespace is None:
508 508 self.use_main_ns = True
509 509 else:
510 510 self.use_main_ns = False
511 511 self.namespace = namespace
512 512
513 513 # The global namespace, if given, can be bound directly
514 514 if global_namespace is None:
515 515 self.global_namespace = {}
516 516 else:
517 517 self.global_namespace = global_namespace
518 518
519 519 super(Completer, self).__init__(**kwargs)
520 520
521 521 def complete(self, text, state):
522 522 """Return the next possible completion for 'text'.
523 523
524 524 This is called successively with state == 0, 1, 2, ... until it
525 525 returns None. The completion should begin with 'text'.
526 526
527 527 """
528 528 if self.use_main_ns:
529 529 self.namespace = __main__.__dict__
530 530
531 531 if state == 0:
532 532 if "." in text:
533 533 self.matches = self.attr_matches(text)
534 534 else:
535 535 self.matches = self.global_matches(text)
536 536 try:
537 537 return self.matches[state]
538 538 except IndexError:
539 539 return None
540 540
541 541 def global_matches(self, text):
542 542 """Compute matches when text is a simple name.
543 543
544 544 Return a list of all keywords, built-in functions and names currently
545 545 defined in self.namespace or self.global_namespace that match.
546 546
547 547 """
548 548 matches = []
549 549 match_append = matches.append
550 550 n = len(text)
551 551 for lst in [keyword.kwlist,
552 552 builtin_mod.__dict__.keys(),
553 553 self.namespace.keys(),
554 554 self.global_namespace.keys()]:
555 555 for word in lst:
556 556 if word[:n] == text and word != "__builtins__":
557 557 match_append(word)
558 558 return [cast_unicode_py2(m) for m in matches]
559 559
560 560 def attr_matches(self, text):
561 561 """Compute matches when text contains a dot.
562 562
563 563 Assuming the text is of the form NAME.NAME....[NAME], and is
564 564 evaluatable in self.namespace or self.global_namespace, it will be
565 565 evaluated and its attributes (as revealed by dir()) are used as
566 566 possible completions. (For class instances, class members are are
567 567 also considered.)
568 568
569 569 WARNING: this can still invoke arbitrary C code, if an object
570 570 with a __getattr__ hook is evaluated.
571 571
572 572 """
573 573
574 574 # Another option, seems to work great. Catches things like ''.<tab>
575 575 m = re.match(r"(\S+(\.\w+)*)\.(\w*)$", text)
576 576
577 577 if m:
578 578 expr, attr = m.group(1, 3)
579 579 elif self.greedy:
580 580 m2 = re.match(r"(.+)\.(\w*)$", self.line_buffer)
581 581 if not m2:
582 582 return []
583 583 expr, attr = m2.group(1,2)
584 584 else:
585 585 return []
586 586
587 587 try:
588 588 obj = eval(expr, self.namespace)
589 589 except:
590 590 try:
591 591 obj = eval(expr, self.global_namespace)
592 592 except:
593 593 return []
594 594
595 595 if self.limit_to__all__ and hasattr(obj, '__all__'):
596 596 words = get__all__entries(obj)
597 597 else:
598 598 words = dir2(obj)
599 599
600 600 try:
601 601 words = generics.complete_object(obj, words)
602 602 except TryNext:
603 603 pass
604 604 except AssertionError:
605 605 raise
606 606 except Exception:
607 607 # Silence errors from completion function
608 608 #raise # dbg
609 609 pass
610 610 # Build match list to return
611 611 n = len(attr)
612 612 return [u"%s.%s" % (expr, w) for w in words if w[:n] == attr ]
613 613
614 614
615 615 def get__all__entries(obj):
616 616 """returns the strings in the __all__ attribute"""
617 617 try:
618 618 words = getattr(obj, '__all__')
619 619 except:
620 620 return []
621 621
622 622 return [cast_unicode_py2(w) for w in words if isinstance(w, str)]
623 623
624 624
625 def match_dict_keys(keys, prefix, delims):
626 """Used by dict_key_matches, matching the prefix to a list of keys"""
625 def match_dict_keys(keys: List[str], prefix: str, delims: str):
626 """Used by dict_key_matches, matching the prefix to a list of keys
627
628 Parameters
629 ==========
630 keys:
631 list of keys in dictionary currently being completed.
632 prefix:
633 Part of the text already typed by the user. e.g. `mydict[b'fo`
634 delims:
635 String of delimiters to consider when finding the current key.
636
637 Returns
638 =======
639
640 A tuple of three elements: ``quote``, ``token_start``, ``matched``, with
641 ``quote`` being the quote that need to be used to close current string.
642 ``token_start`` the position where the replacement should start occurring,
643 ``matches`` a list of replacement/completion
644
645 """
627 646 if not prefix:
628 647 return None, 0, [repr(k) for k in keys
629 648 if isinstance(k, (str, bytes))]
630 649 quote_match = re.search('["\']', prefix)
631 650 quote = quote_match.group()
632 651 try:
633 652 prefix_str = eval(prefix + quote, {})
634 653 except Exception:
635 654 return None, 0, []
636 655
637 656 pattern = '[^' + ''.join('\\' + c for c in delims) + ']*$'
638 657 token_match = re.search(pattern, prefix, re.UNICODE)
639 658 token_start = token_match.start()
640 659 token_prefix = token_match.group()
641 660
642 # TODO: support bytes in Py3k
643 661 matched = []
644 662 for key in keys:
645 663 try:
646 664 if not key.startswith(prefix_str):
647 665 continue
648 666 except (AttributeError, TypeError, UnicodeError):
649 667 # Python 3+ TypeError on b'a'.startswith('a') or vice-versa
650 668 continue
651 669
652 670 # reformat remainder of key to begin with prefix
653 671 rem = key[len(prefix_str):]
654 672 # force repr wrapped in '
655 rem_repr = repr(rem + '"')
673 rem_repr = repr(rem + '"') if isinstance(rem, str) else repr(rem + b'"')
656 674 if rem_repr.startswith('u') and prefix[0] not in 'uU':
657 675 # Found key is unicode, but prefix is Py2 string.
658 676 # Therefore attempt to interpret key as string.
659 677 try:
660 678 rem_repr = repr(rem.encode('ascii') + '"')
661 679 except UnicodeEncodeError:
662 680 continue
663 681
664 682 rem_repr = rem_repr[1 + rem_repr.index("'"):-2]
665 683 if quote == '"':
666 684 # The entered prefix is quoted with ",
667 685 # but the match is quoted with '.
668 686 # A contained " hence needs escaping for comparison:
669 687 rem_repr = rem_repr.replace('"', '\\"')
670 688
671 689 # then reinsert prefix from start of token
672 690 matched.append('%s%s' % (token_prefix, rem_repr))
673 691 return quote, token_start, matched
674 692
675 693
676 694 def cursor_to_position(text:int, line:int, column:int)->int:
677 695 """
678 696
679 697 Convert the (line,column) position of the cursor in text to an offset in a
680 698 string.
681 699
682 700 Parameter
683 701 ---------
684 702
685 703 text : str
686 704 The text in which to calculate the cursor offset
687 705 line : int
688 706 Line of the cursor; 0-indexed
689 707 column : int
690 708 Column of the cursor 0-indexed
691 709
692 710 Return
693 711 ------
694 712 Position of the cursor in ``text``, 0-indexed.
695 713
696 714 See Also
697 715 --------
698 716 position_to_cursor: reciprocal of this function
699 717
700 718 """
701 719 lines = text.split('\n')
702 720 assert line <= len(lines), '{} <= {}'.format(str(line), str(len(lines)))
703 721
704 722 return sum(len(l) + 1 for l in lines[:line]) + column
705 723
706 724 def position_to_cursor(text:str, offset:int)->(int, int):
707 725 """
708 726 Convert the position of the cursor in text (0 indexed) to a line
709 727 number(0-indexed) and a column number (0-indexed) pair
710 728
711 729 Position should be a valid position in ``text``.
712 730
713 731 Parameter
714 732 ---------
715 733
716 734 text : str
717 735 The text in which to calculate the cursor offset
718 736 offset : int
719 737 Position of the cursor in ``text``, 0-indexed.
720 738
721 739 Return
722 740 ------
723 741 (line, column) : (int, int)
724 742 Line of the cursor; 0-indexed, column of the cursor 0-indexed
725 743
726 744
727 745 See Also
728 746 --------
729 747 cursor_to_position : reciprocal of this function
730 748
731 749
732 750 """
733 751
734 752 assert 0 < offset <= len(text) , "0 < %s <= %s" % (offset , len(text))
735 753
736 754 before = text[:offset]
737 755 blines = before.split('\n') # ! splitnes trim trailing \n
738 756 line = before.count('\n')
739 757 col = len(blines[-1])
740 758 return line, col
741 759
742 760
743 761 def _safe_isinstance(obj, module, class_name):
744 762 """Checks if obj is an instance of module.class_name if loaded
745 763 """
746 764 return (module in sys.modules and
747 765 isinstance(obj, getattr(import_module(module), class_name)))
748 766
749 767
750 768 def back_unicode_name_matches(text):
751 769 u"""Match unicode characters back to unicode name
752 770
753 771 This does ``β˜ƒ`` -> ``\\snowman``
754 772
755 773 Note that snowman is not a valid python3 combining character but will be expanded.
756 774 Though it will not recombine back to the snowman character by the completion machinery.
757 775
758 776 This will not either back-complete standard sequences like \\n, \\b ...
759 777
760 778 Used on Python 3 only.
761 779 """
762 780 if len(text)<2:
763 781 return u'', ()
764 782 maybe_slash = text[-2]
765 783 if maybe_slash != '\\':
766 784 return u'', ()
767 785
768 786 char = text[-1]
769 787 # no expand on quote for completion in strings.
770 788 # nor backcomplete standard ascii keys
771 789 if char in string.ascii_letters or char in ['"',"'"]:
772 790 return u'', ()
773 791 try :
774 792 unic = unicodedata.name(char)
775 793 return '\\'+char,['\\'+unic]
776 794 except KeyError:
777 795 pass
778 796 return u'', ()
779 797
780 798 def back_latex_name_matches(text:str):
781 799 """Match latex characters back to unicode name
782 800
783 801 This does ``\\β„΅`` -> ``\\aleph``
784 802
785 803 Used on Python 3 only.
786 804 """
787 805 if len(text)<2:
788 806 return u'', ()
789 807 maybe_slash = text[-2]
790 808 if maybe_slash != '\\':
791 809 return u'', ()
792 810
793 811
794 812 char = text[-1]
795 813 # no expand on quote for completion in strings.
796 814 # nor backcomplete standard ascii keys
797 815 if char in string.ascii_letters or char in ['"',"'"]:
798 816 return u'', ()
799 817 try :
800 818 latex = reverse_latex_symbol[char]
801 819 # '\\' replace the \ as well
802 820 return '\\'+char,[latex]
803 821 except KeyError:
804 822 pass
805 823 return u'', ()
806 824
807 825
808 826 class IPCompleter(Completer):
809 827 """Extension of the completer class with IPython-specific features"""
810 828
811 829 @observe('greedy')
812 830 def _greedy_changed(self, change):
813 831 """update the splitter and readline delims when greedy is changed"""
814 832 if change['new']:
815 833 self.splitter.delims = GREEDY_DELIMS
816 834 else:
817 835 self.splitter.delims = DELIMS
818 836
819 837 merge_completions = Bool(True,
820 838 help="""Whether to merge completion results into a single list
821 839
822 840 If False, only the completion results from the first non-empty
823 841 completer will be returned.
824 842 """
825 843 ).tag(config=True)
826 844 omit__names = Enum((0,1,2), default_value=2,
827 845 help="""Instruct the completer to omit private method names
828 846
829 847 Specifically, when completing on ``object.<tab>``.
830 848
831 849 When 2 [default]: all names that start with '_' will be excluded.
832 850
833 851 When 1: all 'magic' names (``__foo__``) will be excluded.
834 852
835 853 When 0: nothing will be excluded.
836 854 """
837 855 ).tag(config=True)
838 856 limit_to__all__ = Bool(False,
839 857 help="""
840 858 DEPRECATED as of version 5.0.
841 859
842 860 Instruct the completer to use __all__ for the completion
843 861
844 862 Specifically, when completing on ``object.<tab>``.
845 863
846 864 When True: only those names in obj.__all__ will be included.
847 865
848 866 When False [default]: the __all__ attribute is ignored
849 867 """,
850 868 ).tag(config=True)
851 869
852 870 @observe('limit_to__all__')
853 871 def _limit_to_all_changed(self, change):
854 872 warnings.warn('`IPython.core.IPCompleter.limit_to__all__` configuration '
855 873 'value has been deprecated since IPython 5.0, will be made to have '
856 874 'no effects and then removed in future version of IPython.',
857 875 UserWarning)
858 876
859 877 def __init__(self, shell=None, namespace=None, global_namespace=None,
860 878 use_readline=_deprecation_readline_sentinel, config=None, **kwargs):
861 879 """IPCompleter() -> completer
862 880
863 881 Return a completer object.
864 882
865 883 Parameters
866 884 ----------
867 885
868 886 shell
869 887 a pointer to the ipython shell itself. This is needed
870 888 because this completer knows about magic functions, and those can
871 889 only be accessed via the ipython instance.
872 890
873 891 namespace : dict, optional
874 892 an optional dict where completions are performed.
875 893
876 894 global_namespace : dict, optional
877 895 secondary optional dict for completions, to
878 896 handle cases (such as IPython embedded inside functions) where
879 897 both Python scopes are visible.
880 898
881 899 use_readline : bool, optional
882 900 DEPRECATED, ignored since IPython 6.0, will have no effects
883 901 """
884 902
885 903 self.magic_escape = ESC_MAGIC
886 904 self.splitter = CompletionSplitter()
887 905
888 906 if use_readline is not _deprecation_readline_sentinel:
889 907 warnings.warn('The `use_readline` parameter is deprecated and ignored since IPython 6.0.',
890 908 DeprecationWarning, stacklevel=2)
891 909
892 910 # _greedy_changed() depends on splitter and readline being defined:
893 911 Completer.__init__(self, namespace=namespace, global_namespace=global_namespace,
894 912 config=config, **kwargs)
895 913
896 914 # List where completion matches will be stored
897 915 self.matches = []
898 916 self.shell = shell
899 917 # Regexp to split filenames with spaces in them
900 918 self.space_name_re = re.compile(r'([^\\] )')
901 919 # Hold a local ref. to glob.glob for speed
902 920 self.glob = glob.glob
903 921
904 922 # Determine if we are running on 'dumb' terminals, like (X)Emacs
905 923 # buffers, to avoid completion problems.
906 924 term = os.environ.get('TERM','xterm')
907 925 self.dumb_terminal = term in ['dumb','emacs']
908 926
909 927 # Special handling of backslashes needed in win32 platforms
910 928 if sys.platform == "win32":
911 929 self.clean_glob = self._clean_glob_win32
912 930 else:
913 931 self.clean_glob = self._clean_glob
914 932
915 933 #regexp to parse docstring for function signature
916 934 self.docstring_sig_re = re.compile(r'^[\w|\s.]+\(([^)]*)\).*')
917 935 self.docstring_kwd_re = re.compile(r'[\s|\[]*(\w+)(?:\s*=\s*.*)')
918 936 #use this if positional argument name is also needed
919 937 #= re.compile(r'[\s|\[]*(\w+)(?:\s*=?\s*.*)')
920 938
921 939 # All active matcher routines for completion
922 940 self.matchers = [
923 941 self.python_matches,
924 942 self.file_matches,
925 943 self.magic_matches,
926 944 self.python_func_kw_matches,
927 945 self.dict_key_matches,
928 946 ]
929 947
930 948 # This is set externally by InteractiveShell
931 949 self.custom_completers = None
932 950
933 951 def all_completions(self, text):
934 952 """
935 953 Wrapper around the complete method for the benefit of emacs.
936 954 """
937 955 return self.complete(text)[1]
938 956
939 957 def _clean_glob(self, text):
940 958 return self.glob("%s*" % text)
941 959
942 960 def _clean_glob_win32(self,text):
943 961 return [f.replace("\\","/")
944 962 for f in self.glob("%s*" % text)]
945 963
946 964 def file_matches(self, text):
947 965 """Match filenames, expanding ~USER type strings.
948 966
949 967 Most of the seemingly convoluted logic in this completer is an
950 968 attempt to handle filenames with spaces in them. And yet it's not
951 969 quite perfect, because Python's readline doesn't expose all of the
952 970 GNU readline details needed for this to be done correctly.
953 971
954 972 For a filename with a space in it, the printed completions will be
955 973 only the parts after what's already been typed (instead of the
956 974 full completions, as is normally done). I don't think with the
957 975 current (as of Python 2.3) Python readline it's possible to do
958 976 better."""
959 977
960 978 # chars that require escaping with backslash - i.e. chars
961 979 # that readline treats incorrectly as delimiters, but we
962 980 # don't want to treat as delimiters in filename matching
963 981 # when escaped with backslash
964 982 if text.startswith('!'):
965 983 text = text[1:]
966 984 text_prefix = u'!'
967 985 else:
968 986 text_prefix = u''
969 987
970 988 text_until_cursor = self.text_until_cursor
971 989 # track strings with open quotes
972 990 open_quotes = has_open_quotes(text_until_cursor)
973 991
974 992 if '(' in text_until_cursor or '[' in text_until_cursor:
975 993 lsplit = text
976 994 else:
977 995 try:
978 996 # arg_split ~ shlex.split, but with unicode bugs fixed by us
979 997 lsplit = arg_split(text_until_cursor)[-1]
980 998 except ValueError:
981 999 # typically an unmatched ", or backslash without escaped char.
982 1000 if open_quotes:
983 1001 lsplit = text_until_cursor.split(open_quotes)[-1]
984 1002 else:
985 1003 return []
986 1004 except IndexError:
987 1005 # tab pressed on empty line
988 1006 lsplit = ""
989 1007
990 1008 if not open_quotes and lsplit != protect_filename(lsplit):
991 1009 # if protectables are found, do matching on the whole escaped name
992 1010 has_protectables = True
993 1011 text0,text = text,lsplit
994 1012 else:
995 1013 has_protectables = False
996 1014 text = os.path.expanduser(text)
997 1015
998 1016 if text == "":
999 1017 return [text_prefix + cast_unicode_py2(protect_filename(f)) for f in self.glob("*")]
1000 1018
1001 1019 # Compute the matches from the filesystem
1002 1020 if sys.platform == 'win32':
1003 1021 m0 = self.clean_glob(text)
1004 1022 else:
1005 1023 m0 = self.clean_glob(text.replace('\\', ''))
1006 1024
1007 1025 if has_protectables:
1008 1026 # If we had protectables, we need to revert our changes to the
1009 1027 # beginning of filename so that we don't double-write the part
1010 1028 # of the filename we have so far
1011 1029 len_lsplit = len(lsplit)
1012 1030 matches = [text_prefix + text0 +
1013 1031 protect_filename(f[len_lsplit:]) for f in m0]
1014 1032 else:
1015 1033 if open_quotes:
1016 1034 # if we have a string with an open quote, we don't need to
1017 1035 # protect the names at all (and we _shouldn't_, as it
1018 1036 # would cause bugs when the filesystem call is made).
1019 1037 matches = m0
1020 1038 else:
1021 1039 matches = [text_prefix +
1022 1040 protect_filename(f) for f in m0]
1023 1041
1024 1042 # Mark directories in input list by appending '/' to their names.
1025 1043 return [cast_unicode_py2(x+'/') if os.path.isdir(x) else x for x in matches]
1026 1044
1027 1045 def magic_matches(self, text):
1028 1046 """Match magics"""
1029 1047 # Get all shell magics now rather than statically, so magics loaded at
1030 1048 # runtime show up too.
1031 1049 lsm = self.shell.magics_manager.lsmagic()
1032 1050 line_magics = lsm['line']
1033 1051 cell_magics = lsm['cell']
1034 1052 pre = self.magic_escape
1035 1053 pre2 = pre+pre
1036 1054
1037 1055 # Completion logic:
1038 1056 # - user gives %%: only do cell magics
1039 1057 # - user gives %: do both line and cell magics
1040 1058 # - no prefix: do both
1041 1059 # In other words, line magics are skipped if the user gives %% explicitly
1042 1060 bare_text = text.lstrip(pre)
1043 1061 comp = [ pre2+m for m in cell_magics if m.startswith(bare_text)]
1044 1062 if not text.startswith(pre2):
1045 1063 comp += [ pre+m for m in line_magics if m.startswith(bare_text)]
1046 1064 return [cast_unicode_py2(c) for c in comp]
1047 1065
1048 1066 def _jedi_matches(self, cursor_column:int, cursor_line:int, text:str):
1049 1067 """
1050 1068
1051 1069 Return a list of :any:`jedi.api.Completions` object from a ``text`` and
1052 1070 cursor position.
1053 1071
1054 1072 Parameters
1055 1073 ----------
1056 1074 cursor_column : int
1057 1075 column position of the cursor in ``text``, 0-indexed.
1058 1076 cursor_line : int
1059 1077 line position of the cursor in ``text``, 0-indexed
1060 1078 text : str
1061 1079 text to complete
1062 1080
1063 1081 Debugging
1064 1082 ---------
1065 1083
1066 1084 If ``IPCompleter.debug`` is ``True`` may return a :any:`_FakeJediCompletion`
1067 1085 object containing a string with the Jedi debug information attached.
1068 1086 """
1069 1087 namespaces = [self.namespace]
1070 1088 if self.global_namespace is not None:
1071 1089 namespaces.append(self.global_namespace)
1072 1090
1073 1091 # cursor_pos is an it, jedi wants line and column
1074 1092 offset = cursor_to_position(text, cursor_line, cursor_column)
1075 1093 if offset:
1076 1094 pre = text[offset-1]
1077 1095 completion_filter = lambda x:x
1078 1096 if pre == '.':
1079 1097 if self.omit__names == 2:
1080 1098 completion_filter = lambda c:not c.name.startswith('_')
1081 1099 elif self.omit__names == 1:
1082 1100 completion_filter = lambda c:not (c.name.startswith('__') and c.name.endswith('__'))
1083 1101 elif self.omit__names == 0:
1084 1102 completion_filter = lambda x:x
1085 1103 else:
1086 1104 raise ValueError("Don't understand self.omit__names == {}".format(self.omit__names))
1087 1105
1088 1106 interpreter = jedi.Interpreter(
1089 1107 text, namespaces, column=cursor_column, line=cursor_line + 1)
1090 1108 try:
1091 1109 return filter(completion_filter, interpreter.completions())
1092 1110 except Exception as e:
1093 1111 if self.debug:
1094 1112 return [_FakeJediCompletion('Opps Jedi has crash please report a bug with the following:\n"""\n%s\ns"""' % (e))]
1095 1113 else:
1096 1114 return []
1097 1115
1098 1116 def python_matches(self, text):
1099 1117 """Match attributes or global python names"""
1100 1118 if "." in text:
1101 1119 try:
1102 1120 matches = self.attr_matches(text)
1103 1121 if text.endswith('.') and self.omit__names:
1104 1122 if self.omit__names == 1:
1105 1123 # true if txt is _not_ a __ name, false otherwise:
1106 1124 no__name = (lambda txt:
1107 1125 re.match(r'.*\.__.*?__',txt) is None)
1108 1126 else:
1109 1127 # true if txt is _not_ a _ name, false otherwise:
1110 1128 no__name = (lambda txt:
1111 1129 re.match(r'\._.*?',txt[txt.rindex('.'):]) is None)
1112 1130 matches = filter(no__name, matches)
1113 1131 except NameError:
1114 1132 # catches <undefined attributes>.<tab>
1115 1133 matches = []
1116 1134 else:
1117 1135 matches = self.global_matches(text)
1118 1136 return matches
1119 1137
1120 1138 def _default_arguments_from_docstring(self, doc):
1121 1139 """Parse the first line of docstring for call signature.
1122 1140
1123 1141 Docstring should be of the form 'min(iterable[, key=func])\n'.
1124 1142 It can also parse cython docstring of the form
1125 1143 'Minuit.migrad(self, int ncall=10000, resume=True, int nsplit=1)'.
1126 1144 """
1127 1145 if doc is None:
1128 1146 return []
1129 1147
1130 1148 #care only the firstline
1131 1149 line = doc.lstrip().splitlines()[0]
1132 1150
1133 1151 #p = re.compile(r'^[\w|\s.]+\(([^)]*)\).*')
1134 1152 #'min(iterable[, key=func])\n' -> 'iterable[, key=func]'
1135 1153 sig = self.docstring_sig_re.search(line)
1136 1154 if sig is None:
1137 1155 return []
1138 1156 # iterable[, key=func]' -> ['iterable[' ,' key=func]']
1139 1157 sig = sig.groups()[0].split(',')
1140 1158 ret = []
1141 1159 for s in sig:
1142 1160 #re.compile(r'[\s|\[]*(\w+)(?:\s*=\s*.*)')
1143 1161 ret += self.docstring_kwd_re.findall(s)
1144 1162 return ret
1145 1163
1146 1164 def _default_arguments(self, obj):
1147 1165 """Return the list of default arguments of obj if it is callable,
1148 1166 or empty list otherwise."""
1149 1167 call_obj = obj
1150 1168 ret = []
1151 1169 if inspect.isbuiltin(obj):
1152 1170 pass
1153 1171 elif not (inspect.isfunction(obj) or inspect.ismethod(obj)):
1154 1172 if inspect.isclass(obj):
1155 1173 #for cython embededsignature=True the constructor docstring
1156 1174 #belongs to the object itself not __init__
1157 1175 ret += self._default_arguments_from_docstring(
1158 1176 getattr(obj, '__doc__', ''))
1159 1177 # for classes, check for __init__,__new__
1160 1178 call_obj = (getattr(obj, '__init__', None) or
1161 1179 getattr(obj, '__new__', None))
1162 1180 # for all others, check if they are __call__able
1163 1181 elif hasattr(obj, '__call__'):
1164 1182 call_obj = obj.__call__
1165 1183 ret += self._default_arguments_from_docstring(
1166 1184 getattr(call_obj, '__doc__', ''))
1167 1185
1168 1186 _keeps = (inspect.Parameter.KEYWORD_ONLY,
1169 1187 inspect.Parameter.POSITIONAL_OR_KEYWORD)
1170 1188
1171 1189 try:
1172 1190 sig = inspect.signature(call_obj)
1173 1191 ret.extend(k for k, v in sig.parameters.items() if
1174 1192 v.kind in _keeps)
1175 1193 except ValueError:
1176 1194 pass
1177 1195
1178 1196 return list(set(ret))
1179 1197
1180 1198 def python_func_kw_matches(self,text):
1181 1199 """Match named parameters (kwargs) of the last open function"""
1182 1200
1183 1201 if "." in text: # a parameter cannot be dotted
1184 1202 return []
1185 1203 try: regexp = self.__funcParamsRegex
1186 1204 except AttributeError:
1187 1205 regexp = self.__funcParamsRegex = re.compile(r'''
1188 1206 '.*?(?<!\\)' | # single quoted strings or
1189 1207 ".*?(?<!\\)" | # double quoted strings or
1190 1208 \w+ | # identifier
1191 1209 \S # other characters
1192 1210 ''', re.VERBOSE | re.DOTALL)
1193 1211 # 1. find the nearest identifier that comes before an unclosed
1194 1212 # parenthesis before the cursor
1195 1213 # e.g. for "foo (1+bar(x), pa<cursor>,a=1)", the candidate is "foo"
1196 1214 tokens = regexp.findall(self.text_until_cursor)
1197 1215 iterTokens = reversed(tokens); openPar = 0
1198 1216
1199 1217 for token in iterTokens:
1200 1218 if token == ')':
1201 1219 openPar -= 1
1202 1220 elif token == '(':
1203 1221 openPar += 1
1204 1222 if openPar > 0:
1205 1223 # found the last unclosed parenthesis
1206 1224 break
1207 1225 else:
1208 1226 return []
1209 1227 # 2. Concatenate dotted names ("foo.bar" for "foo.bar(x, pa" )
1210 1228 ids = []
1211 1229 isId = re.compile(r'\w+$').match
1212 1230
1213 1231 while True:
1214 1232 try:
1215 1233 ids.append(next(iterTokens))
1216 1234 if not isId(ids[-1]):
1217 1235 ids.pop(); break
1218 1236 if not next(iterTokens) == '.':
1219 1237 break
1220 1238 except StopIteration:
1221 1239 break
1222 1240
1223 1241 # Find all named arguments already assigned to, as to avoid suggesting
1224 1242 # them again
1225 1243 usedNamedArgs = set()
1226 1244 par_level = -1
1227 1245 for token, next_token in zip(tokens, tokens[1:]):
1228 1246 if token == '(':
1229 1247 par_level += 1
1230 1248 elif token == ')':
1231 1249 par_level -= 1
1232 1250
1233 1251 if par_level != 0:
1234 1252 continue
1235 1253
1236 1254 if next_token != '=':
1237 1255 continue
1238 1256
1239 1257 usedNamedArgs.add(token)
1240 1258
1241 1259 # lookup the candidate callable matches either using global_matches
1242 1260 # or attr_matches for dotted names
1243 1261 if len(ids) == 1:
1244 1262 callableMatches = self.global_matches(ids[0])
1245 1263 else:
1246 1264 callableMatches = self.attr_matches('.'.join(ids[::-1]))
1247 1265 argMatches = []
1248 1266 for callableMatch in callableMatches:
1249 1267 try:
1250 1268 namedArgs = self._default_arguments(eval(callableMatch,
1251 1269 self.namespace))
1252 1270 except:
1253 1271 continue
1254 1272
1255 1273 # Remove used named arguments from the list, no need to show twice
1256 1274 for namedArg in set(namedArgs) - usedNamedArgs:
1257 1275 if namedArg.startswith(text):
1258 1276 argMatches.append(u"%s=" %namedArg)
1259 1277 return argMatches
1260 1278
1261 1279 def dict_key_matches(self, text):
1262 1280 "Match string keys in a dictionary, after e.g. 'foo[' "
1263 1281 def get_keys(obj):
1264 1282 # Objects can define their own completions by defining an
1265 1283 # _ipy_key_completions_() method.
1266 1284 method = get_real_method(obj, '_ipython_key_completions_')
1267 1285 if method is not None:
1268 1286 return method()
1269 1287
1270 1288 # Special case some common in-memory dict-like types
1271 1289 if isinstance(obj, dict) or\
1272 1290 _safe_isinstance(obj, 'pandas', 'DataFrame'):
1273 1291 try:
1274 1292 return list(obj.keys())
1275 1293 except Exception:
1276 1294 return []
1277 1295 elif _safe_isinstance(obj, 'numpy', 'ndarray') or\
1278 1296 _safe_isinstance(obj, 'numpy', 'void'):
1279 1297 return obj.dtype.names or []
1280 1298 return []
1281 1299
1282 1300 try:
1283 1301 regexps = self.__dict_key_regexps
1284 1302 except AttributeError:
1285 1303 dict_key_re_fmt = r'''(?x)
1286 1304 ( # match dict-referring expression wrt greedy setting
1287 1305 %s
1288 1306 )
1289 1307 \[ # open bracket
1290 1308 \s* # and optional whitespace
1291 1309 ([uUbB]? # string prefix (r not handled)
1292 1310 (?: # unclosed string
1293 1311 '(?:[^']|(?<!\\)\\')*
1294 1312 |
1295 1313 "(?:[^"]|(?<!\\)\\")*
1296 1314 )
1297 1315 )?
1298 1316 $
1299 1317 '''
1300 1318 regexps = self.__dict_key_regexps = {
1301 1319 False: re.compile(dict_key_re_fmt % '''
1302 1320 # identifiers separated by .
1303 1321 (?!\d)\w+
1304 1322 (?:\.(?!\d)\w+)*
1305 1323 '''),
1306 1324 True: re.compile(dict_key_re_fmt % '''
1307 1325 .+
1308 1326 ''')
1309 1327 }
1310 1328
1311 1329 match = regexps[self.greedy].search(self.text_until_cursor)
1312 1330 if match is None:
1313 1331 return []
1314 1332
1315 1333 expr, prefix = match.groups()
1316 1334 try:
1317 1335 obj = eval(expr, self.namespace)
1318 1336 except Exception:
1319 1337 try:
1320 1338 obj = eval(expr, self.global_namespace)
1321 1339 except Exception:
1322 1340 return []
1323 1341
1324 1342 keys = get_keys(obj)
1325 1343 if not keys:
1326 1344 return keys
1327 1345 closing_quote, token_offset, matches = match_dict_keys(keys, prefix, self.splitter.delims)
1328 1346 if not matches:
1329 1347 return matches
1330 1348
1331 1349 # get the cursor position of
1332 1350 # - the text being completed
1333 1351 # - the start of the key text
1334 1352 # - the start of the completion
1335 1353 text_start = len(self.text_until_cursor) - len(text)
1336 1354 if prefix:
1337 1355 key_start = match.start(2)
1338 1356 completion_start = key_start + token_offset
1339 1357 else:
1340 1358 key_start = completion_start = match.end()
1341 1359
1342 1360 # grab the leading prefix, to make sure all completions start with `text`
1343 1361 if text_start > key_start:
1344 1362 leading = ''
1345 1363 else:
1346 1364 leading = text[text_start:completion_start]
1347 1365
1348 1366 # the index of the `[` character
1349 1367 bracket_idx = match.end(1)
1350 1368
1351 1369 # append closing quote and bracket as appropriate
1352 1370 # this is *not* appropriate if the opening quote or bracket is outside
1353 1371 # the text given to this method
1354 1372 suf = ''
1355 1373 continuation = self.line_buffer[len(self.text_until_cursor):]
1356 1374 if key_start > text_start and closing_quote:
1357 1375 # quotes were opened inside text, maybe close them
1358 1376 if continuation.startswith(closing_quote):
1359 1377 continuation = continuation[len(closing_quote):]
1360 1378 else:
1361 1379 suf += closing_quote
1362 1380 if bracket_idx > text_start:
1363 1381 # brackets were opened inside text, maybe close them
1364 1382 if not continuation.startswith(']'):
1365 1383 suf += ']'
1366 1384
1367 1385 return [leading + k + suf for k in matches]
1368 1386
1369 1387 def unicode_name_matches(self, text):
1370 1388 u"""Match Latex-like syntax for unicode characters base
1371 1389 on the name of the character.
1372 1390
1373 1391 This does ``\\GREEK SMALL LETTER ETA`` -> ``Ξ·``
1374 1392
1375 1393 Works only on valid python 3 identifier, or on combining characters that
1376 1394 will combine to form a valid identifier.
1377 1395
1378 1396 Used on Python 3 only.
1379 1397 """
1380 1398 slashpos = text.rfind('\\')
1381 1399 if slashpos > -1:
1382 1400 s = text[slashpos+1:]
1383 1401 try :
1384 1402 unic = unicodedata.lookup(s)
1385 1403 # allow combining chars
1386 1404 if ('a'+unic).isidentifier():
1387 1405 return '\\'+s,[unic]
1388 1406 except KeyError:
1389 1407 pass
1390 1408 return u'', []
1391 1409
1392 1410
1393 1411 def latex_matches(self, text):
1394 1412 u"""Match Latex syntax for unicode characters.
1395 1413
1396 1414 This does both ``\\alp`` -> ``\\alpha`` and ``\\alpha`` -> ``Ξ±``
1397 1415
1398 1416 Used on Python 3 only.
1399 1417 """
1400 1418 slashpos = text.rfind('\\')
1401 1419 if slashpos > -1:
1402 1420 s = text[slashpos:]
1403 1421 if s in latex_symbols:
1404 1422 # Try to complete a full latex symbol to unicode
1405 1423 # \\alpha -> Ξ±
1406 1424 return s, [latex_symbols[s]]
1407 1425 else:
1408 1426 # If a user has partially typed a latex symbol, give them
1409 1427 # a full list of options \al -> [\aleph, \alpha]
1410 1428 matches = [k for k in latex_symbols if k.startswith(s)]
1411 1429 return s, matches
1412 1430 return u'', []
1413 1431
1414 1432 def dispatch_custom_completer(self, text):
1415 1433 if not self.custom_completers:
1416 1434 return
1417 1435
1418 1436 line = self.line_buffer
1419 1437 if not line.strip():
1420 1438 return None
1421 1439
1422 1440 # Create a little structure to pass all the relevant information about
1423 1441 # the current completion to any custom completer.
1424 1442 event = SimpleNamespace()
1425 1443 event.line = line
1426 1444 event.symbol = text
1427 1445 cmd = line.split(None,1)[0]
1428 1446 event.command = cmd
1429 1447 event.text_until_cursor = self.text_until_cursor
1430 1448
1431 1449 # for foo etc, try also to find completer for %foo
1432 1450 if not cmd.startswith(self.magic_escape):
1433 1451 try_magic = self.custom_completers.s_matches(
1434 1452 self.magic_escape + cmd)
1435 1453 else:
1436 1454 try_magic = []
1437 1455
1438 1456 for c in itertools.chain(self.custom_completers.s_matches(cmd),
1439 1457 try_magic,
1440 1458 self.custom_completers.flat_matches(self.text_until_cursor)):
1441 1459 try:
1442 1460 res = c(event)
1443 1461 if res:
1444 1462 # first, try case sensitive match
1445 1463 withcase = [cast_unicode_py2(r) for r in res if r.startswith(text)]
1446 1464 if withcase:
1447 1465 return withcase
1448 1466 # if none, then case insensitive ones are ok too
1449 1467 text_low = text.lower()
1450 1468 return [cast_unicode_py2(r) for r in res if r.lower().startswith(text_low)]
1451 1469 except TryNext:
1452 1470 pass
1453 1471
1454 1472 return None
1455 1473
1456 1474 def completions(self, text: str, offset: int)->Iterator[Completion]:
1457 1475 """
1458 1476 Returns an iterator over the possible completions
1459 1477
1460 1478 .. warning:: Unstable
1461 1479
1462 1480 This function is unstable, API may change without warning.
1463 1481 It will also raise unless use in proper context manager.
1464 1482
1465 1483 Parameters
1466 1484 ----------
1467 1485
1468 1486 text:str
1469 1487 Full text of the current input, multi line string.
1470 1488 offset:int
1471 1489 Integer representing the position of the cursor in ``text``. Offset
1472 1490 is 0-based indexed.
1473 1491
1474 1492 Yields
1475 1493 ------
1476 1494 :any:`Completion` object
1477 1495
1478 1496
1479 1497 The cursor on a text can either be seen as being "in between"
1480 1498 characters or "On" a character depending on the interface visible to
1481 1499 the user. For consistency the cursor being on "in between" characters X
1482 1500 and Y is equivalent to the cursor being "on" character Y, that is to say
1483 1501 the character the cursor is on is considered as being after the cursor.
1484 1502
1485 1503 Combining characters may span more that one position in the
1486 1504 text.
1487 1505
1488 1506
1489 1507 .. note::
1490 1508
1491 1509 If ``IPCompleter.debug`` is :any:`True` will yield a ``--jedi/ipython--``
1492 1510 fake Completion token to distinguish completion returned by Jedi
1493 1511 and usual IPython completion.
1494 1512
1495 1513 """
1496 1514 warnings.warn("_complete is a provisional API (as of IPython 6.0). "
1497 1515 "It may change without warnings. "
1498 1516 "Use in corresponding context manager.",
1499 1517 category=ProvisionalCompleterWarning, stacklevel=2)
1500 1518
1501 1519 # Possible Improvements / Known limitation
1502 1520 ##########################################
1503 1521 # Completions may be identical even if they have different ranges and
1504 1522 # text. For example:
1505 1523 # >>> a=1
1506 1524 # >>> a.<tab>
1507 1525 # May returns:
1508 1526 # - `a.real` from 0 to 2
1509 1527 # - `.real` from 1 to 2
1510 1528 # the current code does not (yet) check for such equivalence
1511 1529 seen = set()
1512 1530 for c in self._completions(text, offset, _timeout=self.jedi_compute_type_timeout/1000):
1513 1531 if c and (c in seen):
1514 1532 continue
1515 1533 yield c
1516 1534 seen.add(c)
1517 1535
1518 1536 def _completions(self, full_text: str, offset: int, *, _timeout)->Iterator[Completion]:
1519 1537 """
1520 1538 Core completion module.Same signature as :any:`completions`, with the
1521 1539 extra `timeout` parameter (in seconds).
1522 1540
1523 1541
1524 1542 Computing jedi's completion ``.type`` can be quite expensive (it is a
1525 1543 lazy property) and can require some warm-up, more warm up than just
1526 1544 computing the ``name`` of a completion. The warm-up can be :
1527 1545
1528 1546 - Long warm-up the fisrt time a module is encountered after
1529 1547 install/update: actually build parse/inference tree.
1530 1548
1531 1549 - first time the module is encountered in a session: load tree from
1532 1550 disk.
1533 1551
1534 1552 We don't want to block completions for tens of seconds so we give the
1535 1553 completer a "budget" of ``_timeout`` seconds per invocation to compute
1536 1554 completions types, the completions that have not yet been computed will
1537 1555 be marked as "unknown" an will have a chance to be computed next round
1538 1556 are things get cached.
1539 1557
1540 1558 Keep in mind that Jedi is not the only thing treating the completion so
1541 1559 keep the timeout short-ish as if we take more than 0.3 second we still
1542 1560 have lots of processing to do.
1543 1561
1544 1562 """
1545 1563 deadline = time.monotonic() + _timeout
1546 1564
1547 1565
1548 1566 before = full_text[:offset]
1549 1567 cursor_line, cursor_column = position_to_cursor(full_text, offset)
1550 1568
1551 1569 matched_text, matches, matches_origin, jedi_matches = self._complete(
1552 1570 full_text=full_text, cursor_line=cursor_line, cursor_pos=cursor_column)
1553 1571
1554 1572 iter_jm = iter(jedi_matches)
1555 1573 if _timeout:
1556 1574 for jm in iter_jm:
1557 1575 try:
1558 1576 type_ = jm.type
1559 1577 except Exception:
1560 1578 if self.debug:
1561 1579 print("Error in Jedi getting type of ", jm)
1562 1580 type_ = None
1563 1581 delta = len(jm.name_with_symbols) - len(jm.complete)
1564 1582 yield Completion(start=offset - delta,
1565 1583 end=offset,
1566 1584 text=jm.name_with_symbols,
1567 1585 type=type_,
1568 1586 _origin='jedi')
1569 1587
1570 1588 if time.monotonic() > deadline:
1571 1589 break
1572 1590
1573 1591 for jm in iter_jm:
1574 1592 delta = len(jm.name_with_symbols) - len(jm.complete)
1575 1593 yield Completion(start=offset - delta,
1576 1594 end=offset,
1577 1595 text=jm.name_with_symbols,
1578 1596 type='<unknown>', # don't compute type for speed
1579 1597 _origin='jedi')
1580 1598
1581 1599
1582 1600 start_offset = before.rfind(matched_text)
1583 1601
1584 1602 # TODO:
1585 1603 # Supress this, right now just for debug.
1586 1604 if jedi_matches and matches and self.debug:
1587 1605 yield Completion(start=start_offset, end=offset, text='--jedi/ipython--', _origin='debug')
1588 1606
1589 1607 # I'm unsure if this is always true, so let's assert and see if it
1590 1608 # crash
1591 1609 assert before.endswith(matched_text)
1592 1610 for m, t in zip(matches, matches_origin):
1593 1611 yield Completion(start=start_offset, end=offset, text=m, _origin=t)
1594 1612
1595 1613
1596 1614 def complete(self, text=None, line_buffer=None, cursor_pos=None):
1597 1615 """Find completions for the given text and line context.
1598 1616
1599 1617 Note that both the text and the line_buffer are optional, but at least
1600 1618 one of them must be given.
1601 1619
1602 1620 Parameters
1603 1621 ----------
1604 1622 text : string, optional
1605 1623 Text to perform the completion on. If not given, the line buffer
1606 1624 is split using the instance's CompletionSplitter object.
1607 1625
1608 1626 line_buffer : string, optional
1609 1627 If not given, the completer attempts to obtain the current line
1610 1628 buffer via readline. This keyword allows clients which are
1611 1629 requesting for text completions in non-readline contexts to inform
1612 1630 the completer of the entire text.
1613 1631
1614 1632 cursor_pos : int, optional
1615 1633 Index of the cursor in the full line buffer. Should be provided by
1616 1634 remote frontends where kernel has no access to frontend state.
1617 1635
1618 1636 Returns
1619 1637 -------
1620 1638 text : str
1621 1639 Text that was actually used in the completion.
1622 1640
1623 1641 matches : list
1624 1642 A list of completion matches.
1625 1643
1626 1644
1627 1645 .. note::
1628 1646
1629 1647 This API is likely to be deprecated and replaced by
1630 1648 :any:`IPCompleter.completions` in the future.
1631 1649
1632 1650
1633 1651 """
1634 1652 warnings.warn('`Completer.complete` is pending deprecation since '
1635 1653 'IPython 6.0 and will be replaced by `Completer.completions`.',
1636 1654 PendingDeprecationWarning)
1637 1655 # potential todo, FOLD the 3rd throw away argument of _complete
1638 1656 # into the first 2 one.
1639 1657 return self._complete(line_buffer=line_buffer, cursor_pos=cursor_pos, text=text, cursor_line=0)[:2]
1640 1658
1641 1659 def _complete(self, *, cursor_line, cursor_pos, line_buffer=None, text=None,
1642 1660 full_text=None, return_jedi_results=True) -> (str, List[str], List[object]):
1643 1661 """
1644 1662
1645 1663 Like complete but can also returns raw jedi completions as well as the
1646 1664 origin of the completion text. This could (and should) be made much
1647 1665 cleaner but that will be simpler once we drop the old (and stateful)
1648 1666 :any:`complete` API.
1649 1667
1650 1668
1651 1669 With current provisional API, cursor_pos act both (depending on the
1652 1670 caller) as the offset in the ``text`` or ``line_buffer``, or as the
1653 1671 ``column`` when passing multiline strings this could/should be renamed
1654 1672 but would add extra noise.
1655 1673 """
1656 1674
1657 1675 # if the cursor position isn't given, the only sane assumption we can
1658 1676 # make is that it's at the end of the line (the common case)
1659 1677 if cursor_pos is None:
1660 1678 cursor_pos = len(line_buffer) if text is None else len(text)
1661 1679
1662 1680 if self.use_main_ns:
1663 1681 self.namespace = __main__.__dict__
1664 1682
1665 1683 # if text is either None or an empty string, rely on the line buffer
1666 1684 if (not line_buffer) and full_text:
1667 1685 line_buffer = full_text.split('\n')[cursor_line]
1668 1686 if not text:
1669 1687 text = self.splitter.split_line(line_buffer, cursor_pos)
1670 1688
1671 1689 base_text = text if not line_buffer else line_buffer[:cursor_pos]
1672 1690 latex_text, latex_matches = self.latex_matches(base_text)
1673 1691 if latex_matches:
1674 1692 return latex_text, latex_matches, ['latex_matches']*len(latex_matches), ()
1675 1693 name_text = ''
1676 1694 name_matches = []
1677 1695 for meth in (self.unicode_name_matches, back_latex_name_matches, back_unicode_name_matches):
1678 1696 name_text, name_matches = meth(base_text)
1679 1697 if name_text:
1680 1698 return name_text, name_matches, [meth.__qualname__]*len(name_matches), {}
1681 1699
1682 1700
1683 1701 # If no line buffer is given, assume the input text is all there was
1684 1702 if line_buffer is None:
1685 1703 line_buffer = text
1686 1704
1687 1705 self.line_buffer = line_buffer
1688 1706 self.text_until_cursor = self.line_buffer[:cursor_pos]
1689 1707
1690 1708 # Start with a clean slate of completions
1691 1709 matches = []
1692 1710 custom_res = self.dispatch_custom_completer(text)
1693 1711 # FIXME: we should extend our api to return a dict with completions for
1694 1712 # different types of objects. The rlcomplete() method could then
1695 1713 # simply collapse the dict into a list for readline, but we'd have
1696 1714 # richer completion semantics in other evironments.
1697 1715 completions = ()
1698 1716 if self.use_jedi and return_jedi_results:
1699 1717 if not full_text:
1700 1718 full_text = line_buffer
1701 1719 completions = self._jedi_matches(
1702 1720 cursor_pos, cursor_line, full_text)
1703 1721 if custom_res is not None:
1704 1722 # did custom completers produce something?
1705 1723 matches = [(m, 'custom') for m in custom_res]
1706 1724 else:
1707 1725 # Extend the list of completions with the results of each
1708 1726 # matcher, so we return results to the user from all
1709 1727 # namespaces.
1710 1728 if self.merge_completions:
1711 1729 matches = []
1712 1730 for matcher in self.matchers:
1713 1731 try:
1714 1732 matches.extend([(m, matcher.__qualname__)
1715 1733 for m in matcher(text)])
1716 1734 except:
1717 1735 # Show the ugly traceback if the matcher causes an
1718 1736 # exception, but do NOT crash the kernel!
1719 1737 sys.excepthook(*sys.exc_info())
1720 1738 else:
1721 1739 for matcher in self.matchers:
1722 1740 matches = [(m, matcher.__qualname__)
1723 1741 for m in matcher(text)]
1724 1742 if matches:
1725 1743 break
1726 1744 seen = set()
1727 1745 filtered_matches = set()
1728 1746 for m in matches:
1729 1747 t, c = m
1730 1748 if t not in seen:
1731 1749 filtered_matches.add(m)
1732 1750 seen.add(t)
1733 1751
1734 1752 filtered_matches = sorted(
1735 1753 set(filtered_matches), key=lambda x: completions_sorting_key(x[0]))
1736 1754
1737 1755 matches = [m[0] for m in filtered_matches]
1738 1756 origins = [m[1] for m in filtered_matches]
1739 1757
1740 1758 self.matches = matches
1741 1759
1742 1760 return text, matches, origins, completions
@@ -1,822 +1,843 b''
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 unittest
10 10
11 11 from contextlib import contextmanager
12 12
13 13 import nose.tools as nt
14 14
15 15 from traitlets.config.loader import Config
16 16 from IPython import get_ipython
17 17 from IPython.core import completer
18 18 from IPython.external.decorators import knownfailureif
19 19 from IPython.utils.tempdir import TemporaryDirectory, TemporaryWorkingDirectory
20 20 from IPython.utils.generics import complete_object
21 21 from IPython.testing import decorators as dec
22 22
23 from IPython.core.completer import Completion, provisionalcompleter
23 from IPython.core.completer import Completion, provisionalcompleter, match_dict_keys
24 24 from nose.tools import assert_in, assert_not_in
25 25
26 26 #-----------------------------------------------------------------------------
27 27 # Test functions
28 28 #-----------------------------------------------------------------------------
29 29
30 30 @contextmanager
31 31 def greedy_completion():
32 32 ip = get_ipython()
33 33 greedy_original = ip.Completer.greedy
34 34 try:
35 35 ip.Completer.greedy = True
36 36 yield
37 37 finally:
38 38 ip.Completer.greedy = greedy_original
39 39
40 40 def test_protect_filename():
41 41 if sys.platform == 'win32':
42 42 pairs = [('abc','abc'),
43 43 (' abc','" abc"'),
44 44 ('a bc','"a bc"'),
45 45 ('a bc','"a bc"'),
46 46 (' bc','" bc"'),
47 47 ]
48 48 else:
49 49 pairs = [('abc','abc'),
50 50 (' abc',r'\ abc'),
51 51 ('a bc',r'a\ bc'),
52 52 ('a bc',r'a\ \ bc'),
53 53 (' bc',r'\ \ bc'),
54 54 # On posix, we also protect parens and other special characters.
55 55 ('a(bc',r'a\(bc'),
56 56 ('a)bc',r'a\)bc'),
57 57 ('a( )bc',r'a\(\ \)bc'),
58 58 ('a[1]bc', r'a\[1\]bc'),
59 59 ('a{1}bc', r'a\{1\}bc'),
60 60 ('a#bc', r'a\#bc'),
61 61 ('a?bc', r'a\?bc'),
62 62 ('a=bc', r'a\=bc'),
63 63 ('a\\bc', r'a\\bc'),
64 64 ('a|bc', r'a\|bc'),
65 65 ('a;bc', r'a\;bc'),
66 66 ('a:bc', r'a\:bc'),
67 67 ("a'bc", r"a\'bc"),
68 68 ('a*bc', r'a\*bc'),
69 69 ('a"bc', r'a\"bc'),
70 70 ('a^bc', r'a\^bc'),
71 71 ('a&bc', r'a\&bc'),
72 72 ]
73 73 # run the actual tests
74 74 for s1, s2 in pairs:
75 75 s1p = completer.protect_filename(s1)
76 76 nt.assert_equal(s1p, s2)
77 77
78 78
79 79 def check_line_split(splitter, test_specs):
80 80 for part1, part2, split in test_specs:
81 81 cursor_pos = len(part1)
82 82 line = part1+part2
83 83 out = splitter.split_line(line, cursor_pos)
84 84 nt.assert_equal(out, split)
85 85
86 86
87 87 def test_line_split():
88 88 """Basic line splitter test with default specs."""
89 89 sp = completer.CompletionSplitter()
90 90 # The format of the test specs is: part1, part2, expected answer. Parts 1
91 91 # and 2 are joined into the 'line' sent to the splitter, as if the cursor
92 92 # was at the end of part1. So an empty part2 represents someone hitting
93 93 # tab at the end of the line, the most common case.
94 94 t = [('run some/scrip', '', 'some/scrip'),
95 95 ('run scripts/er', 'ror.py foo', 'scripts/er'),
96 96 ('echo $HOM', '', 'HOM'),
97 97 ('print sys.pa', '', 'sys.pa'),
98 98 ('print(sys.pa', '', 'sys.pa'),
99 99 ("execfile('scripts/er", '', 'scripts/er'),
100 100 ('a[x.', '', 'x.'),
101 101 ('a[x.', 'y', 'x.'),
102 102 ('cd "some_file/', '', 'some_file/'),
103 103 ]
104 104 check_line_split(sp, t)
105 105 # Ensure splitting works OK with unicode by re-running the tests with
106 106 # all inputs turned into unicode
107 107 check_line_split(sp, [ map(str, p) for p in t] )
108 108
109 109
110 110 def test_custom_completion_error():
111 111 """Test that errors from custom attribute completers are silenced."""
112 112 ip = get_ipython()
113 113 class A(object): pass
114 114 ip.user_ns['a'] = A()
115 115
116 116 @complete_object.when_type(A)
117 117 def complete_A(a, existing_completions):
118 118 raise TypeError("this should be silenced")
119 119
120 120 ip.complete("a.")
121 121
122 122
123 123 def test_unicode_completions():
124 124 ip = get_ipython()
125 125 # Some strings that trigger different types of completion. Check them both
126 126 # in str and unicode forms
127 127 s = ['ru', '%ru', 'cd /', 'floa', 'float(x)/']
128 128 for t in s + list(map(str, s)):
129 129 # We don't need to check exact completion values (they may change
130 130 # depending on the state of the namespace, but at least no exceptions
131 131 # should be thrown and the return value should be a pair of text, list
132 132 # values.
133 133 text, matches = ip.complete(t)
134 134 nt.assert_true(isinstance(text, str))
135 135 nt.assert_true(isinstance(matches, list))
136 136
137 137 def test_latex_completions():
138 138 from IPython.core.latex_symbols import latex_symbols
139 139 import random
140 140 ip = get_ipython()
141 141 # Test some random unicode symbols
142 142 keys = random.sample(latex_symbols.keys(), 10)
143 143 for k in keys:
144 144 text, matches = ip.complete(k)
145 145 nt.assert_equal(len(matches),1)
146 146 nt.assert_equal(text, k)
147 147 nt.assert_equal(matches[0], latex_symbols[k])
148 148 # Test a more complex line
149 149 text, matches = ip.complete(u'print(\\alpha')
150 150 nt.assert_equal(text, u'\\alpha')
151 151 nt.assert_equal(matches[0], latex_symbols['\\alpha'])
152 152 # Test multiple matching latex symbols
153 153 text, matches = ip.complete(u'\\al')
154 154 nt.assert_in('\\alpha', matches)
155 155 nt.assert_in('\\aleph', matches)
156 156
157 157
158 158
159 159
160 160 def test_back_latex_completion():
161 161 ip = get_ipython()
162 162
163 163 # do not return more than 1 matches fro \beta, only the latex one.
164 164 name, matches = ip.complete('\\Ξ²')
165 165 nt.assert_equal(len(matches), 1)
166 166 nt.assert_equal(matches[0], '\\beta')
167 167
168 168 def test_back_unicode_completion():
169 169 ip = get_ipython()
170 170
171 171 name, matches = ip.complete('\\β…€')
172 172 nt.assert_equal(len(matches), 1)
173 173 nt.assert_equal(matches[0], '\\ROMAN NUMERAL FIVE')
174 174
175 175
176 176 def test_forward_unicode_completion():
177 177 ip = get_ipython()
178 178
179 179 name, matches = ip.complete('\\ROMAN NUMERAL FIVE')
180 180 nt.assert_equal(len(matches), 1)
181 181 nt.assert_equal(matches[0], 'β…€')
182 182
183 183 @dec.knownfailureif(sys.platform == 'win32', 'Fails if there is a C:\\j... path')
184 184 def test_no_ascii_back_completion():
185 185 ip = get_ipython()
186 186 with TemporaryWorkingDirectory(): # Avoid any filename completions
187 187 # single ascii letter that don't have yet completions
188 188 for letter in 'jJ' :
189 189 name, matches = ip.complete('\\'+letter)
190 190 nt.assert_equal(matches, [])
191 191
192 192
193 193
194 194
195 195 class CompletionSplitterTestCase(unittest.TestCase):
196 196 def setUp(self):
197 197 self.sp = completer.CompletionSplitter()
198 198
199 199 def test_delim_setting(self):
200 200 self.sp.delims = ' '
201 201 nt.assert_equal(self.sp.delims, ' ')
202 202 nt.assert_equal(self.sp._delim_expr, '[\ ]')
203 203
204 204 def test_spaces(self):
205 205 """Test with only spaces as split chars."""
206 206 self.sp.delims = ' '
207 207 t = [('foo', '', 'foo'),
208 208 ('run foo', '', 'foo'),
209 209 ('run foo', 'bar', 'foo'),
210 210 ]
211 211 check_line_split(self.sp, t)
212 212
213 213
214 214 def test_has_open_quotes1():
215 215 for s in ["'", "'''", "'hi' '"]:
216 216 nt.assert_equal(completer.has_open_quotes(s), "'")
217 217
218 218
219 219 def test_has_open_quotes2():
220 220 for s in ['"', '"""', '"hi" "']:
221 221 nt.assert_equal(completer.has_open_quotes(s), '"')
222 222
223 223
224 224 def test_has_open_quotes3():
225 225 for s in ["''", "''' '''", "'hi' 'ipython'"]:
226 226 nt.assert_false(completer.has_open_quotes(s))
227 227
228 228
229 229 def test_has_open_quotes4():
230 230 for s in ['""', '""" """', '"hi" "ipython"']:
231 231 nt.assert_false(completer.has_open_quotes(s))
232 232
233 233
234 234 @knownfailureif(sys.platform == 'win32', "abspath completions fail on Windows")
235 235 def test_abspath_file_completions():
236 236 ip = get_ipython()
237 237 with TemporaryDirectory() as tmpdir:
238 238 prefix = os.path.join(tmpdir, 'foo')
239 239 suffixes = ['1', '2']
240 240 names = [prefix+s for s in suffixes]
241 241 for n in names:
242 242 open(n, 'w').close()
243 243
244 244 # Check simple completion
245 245 c = ip.complete(prefix)[1]
246 246 nt.assert_equal(c, names)
247 247
248 248 # Now check with a function call
249 249 cmd = 'a = f("%s' % prefix
250 250 c = ip.complete(prefix, cmd)[1]
251 251 comp = [prefix+s for s in suffixes]
252 252 nt.assert_equal(c, comp)
253 253
254 254
255 255 def test_local_file_completions():
256 256 ip = get_ipython()
257 257 with TemporaryWorkingDirectory():
258 258 prefix = './foo'
259 259 suffixes = ['1', '2']
260 260 names = [prefix+s for s in suffixes]
261 261 for n in names:
262 262 open(n, 'w').close()
263 263
264 264 # Check simple completion
265 265 c = ip.complete(prefix)[1]
266 266 nt.assert_equal(c, names)
267 267
268 268 # Now check with a function call
269 269 cmd = 'a = f("%s' % prefix
270 270 c = ip.complete(prefix, cmd)[1]
271 271 comp = set(prefix+s for s in suffixes)
272 272 nt.assert_true(comp.issubset(set(c)))
273 273
274 274
275 275 def test_jedi():
276 276 """
277 277 A couple of issue we had with Jedi
278 278 """
279 279 ip = get_ipython()
280 280
281 281 def _test_complete(reason, s, comp, start=None, end=None):
282 282 l = len(s)
283 283 start = start if start is not None else l
284 284 end = end if end is not None else l
285 285 with provisionalcompleter():
286 286 completions = set(ip.Completer.completions(s, l))
287 287 assert_in(Completion(start, end, comp), completions, reason)
288 288
289 289 def _test_not_complete(reason, s, comp):
290 290 l = len(s)
291 291 with provisionalcompleter():
292 292 completions = set(ip.Completer.completions(s, l))
293 293 assert_not_in(Completion(l, l, comp), completions, reason)
294 294
295 295 import jedi
296 296 jedi_version = tuple(int(i) for i in jedi.__version__.split('.')[:3])
297 297 if jedi_version > (0,10):
298 298 yield _test_complete, 'jedi >0.9 should complete and not crash', 'a=1;a.', 'real'
299 299 yield _test_complete, 'can infer first argument', 'a=(1,"foo");a[0].', 'real'
300 300 yield _test_complete, 'can infer second argument', 'a=(1,"foo");a[1].', 'capitalize'
301 301 yield _test_complete, 'cover duplicate completions', 'im', 'import', 0, 2
302 302
303 303 yield _test_not_complete, 'does not mix types', 'a=(1,"foo");a[0].', 'capitalize'
304 304
305 305
306 306 def test_greedy_completions():
307 307 """
308 308 Test the capability of the Greedy completer.
309 309
310 310 Most of the test here do not really show off the greedy completer, for proof
311 311 each of the text bellow now pass with Jedi. The greedy completer is capable of more.
312 312
313 313 See the :any:`test_dict_key_completion_contexts`
314 314
315 315 """
316 316 ip = get_ipython()
317 317 ip.ex('a=list(range(5))')
318 318 _,c = ip.complete('.',line='a[0].')
319 319 nt.assert_false('.real' in c,
320 320 "Shouldn't have completed on a[0]: %s"%c)
321 321 with greedy_completion(), provisionalcompleter():
322 322 def _(line, cursor_pos, expect, message, completion):
323 323 _,c = ip.complete('.', line=line, cursor_pos=cursor_pos)
324 324 with provisionalcompleter():
325 325 completions = ip.Completer.completions(line, cursor_pos)
326 326 nt.assert_in(expect, c, message%c)
327 327 nt.assert_in(completion, completions)
328 328
329 329 yield _, 'a[0].', 5, 'a[0].real', "Should have completed on a[0].: %s", Completion(5,5, 'real')
330 330 yield _, 'a[0].r', 6, 'a[0].real', "Should have completed on a[0].r: %s", Completion(5,6, 'real')
331 331
332 332 if sys.version_info > (3, 4):
333 333 yield _, 'a[0].from_', 10, 'a[0].from_bytes', "Should have completed on a[0].from_: %s", Completion(5, 10, 'from_bytes')
334 334
335 335
336 336 def test_omit__names():
337 337 # also happens to test IPCompleter as a configurable
338 338 ip = get_ipython()
339 339 ip._hidden_attr = 1
340 340 ip._x = {}
341 341 c = ip.Completer
342 342 ip.ex('ip=get_ipython()')
343 343 cfg = Config()
344 344 cfg.IPCompleter.omit__names = 0
345 345 c.update_config(cfg)
346 346 with provisionalcompleter():
347 347 s,matches = c.complete('ip.')
348 348 completions = set(c.completions('ip.', 3))
349 349
350 350 nt.assert_in('ip.__str__', matches)
351 351 nt.assert_in(Completion(3, 3, '__str__'), completions)
352 352
353 353 nt.assert_in('ip._hidden_attr', matches)
354 354 nt.assert_in(Completion(3,3, "_hidden_attr"), completions)
355 355
356 356
357 357 cfg = Config()
358 358 cfg.IPCompleter.omit__names = 1
359 359 c.update_config(cfg)
360 360 with provisionalcompleter():
361 361 s,matches = c.complete('ip.')
362 362 completions = set(c.completions('ip.', 3))
363 363
364 364 nt.assert_not_in('ip.__str__', matches)
365 365 nt.assert_not_in(Completion(3,3,'__str__'), completions)
366 366
367 367 # nt.assert_in('ip._hidden_attr', matches)
368 368 nt.assert_in(Completion(3,3, "_hidden_attr"), completions)
369 369
370 370 cfg = Config()
371 371 cfg.IPCompleter.omit__names = 2
372 372 c.update_config(cfg)
373 373 with provisionalcompleter():
374 374 s,matches = c.complete('ip.')
375 375 completions = set(c.completions('ip.', 3))
376 376
377 377 nt.assert_not_in('ip.__str__', matches)
378 378 nt.assert_not_in(Completion(3,3,'__str__'), completions)
379 379
380 380 nt.assert_not_in('ip._hidden_attr', matches)
381 381 nt.assert_not_in(Completion(3,3, "_hidden_attr"), completions)
382 382
383 383 with provisionalcompleter():
384 384 s,matches = c.complete('ip._x.')
385 385 completions = set(c.completions('ip._x.', 6))
386 386
387 387 nt.assert_in('ip._x.keys', matches)
388 388 nt.assert_in(Completion(6,6, "keys"), completions)
389 389
390 390 del ip._hidden_attr
391 391 del ip._x
392 392
393 393
394 394 def test_limit_to__all__False_ok():
395 395 """
396 396 Limit to all is deprecated, once we remove it this test can go away.
397 397 """
398 398 ip = get_ipython()
399 399 c = ip.Completer
400 400 ip.ex('class D: x=24')
401 401 ip.ex('d=D()')
402 402 cfg = Config()
403 403 cfg.IPCompleter.limit_to__all__ = False
404 404 c.update_config(cfg)
405 405 s, matches = c.complete('d.')
406 406 nt.assert_in('d.x', matches)
407 407
408 408
409 409 def test_get__all__entries_ok():
410 410 class A(object):
411 411 __all__ = ['x', 1]
412 412 words = completer.get__all__entries(A())
413 413 nt.assert_equal(words, ['x'])
414 414
415 415
416 416 def test_get__all__entries_no__all__ok():
417 417 class A(object):
418 418 pass
419 419 words = completer.get__all__entries(A())
420 420 nt.assert_equal(words, [])
421 421
422 422
423 423 def test_func_kw_completions():
424 424 ip = get_ipython()
425 425 c = ip.Completer
426 426 ip.ex('def myfunc(a=1,b=2): return a+b')
427 427 s, matches = c.complete(None, 'myfunc(1,b')
428 428 nt.assert_in('b=', matches)
429 429 # Simulate completing with cursor right after b (pos==10):
430 430 s, matches = c.complete(None, 'myfunc(1,b)', 10)
431 431 nt.assert_in('b=', matches)
432 432 s, matches = c.complete(None, 'myfunc(a="escaped\\")string",b')
433 433 nt.assert_in('b=', matches)
434 434 #builtin function
435 435 s, matches = c.complete(None, 'min(k, k')
436 436 nt.assert_in('key=', matches)
437 437
438 438
439 439 def test_default_arguments_from_docstring():
440 440 ip = get_ipython()
441 441 c = ip.Completer
442 442 kwd = c._default_arguments_from_docstring(
443 443 'min(iterable[, key=func]) -> value')
444 444 nt.assert_equal(kwd, ['key'])
445 445 #with cython type etc
446 446 kwd = c._default_arguments_from_docstring(
447 447 'Minuit.migrad(self, int ncall=10000, resume=True, int nsplit=1)\n')
448 448 nt.assert_equal(kwd, ['ncall', 'resume', 'nsplit'])
449 449 #white spaces
450 450 kwd = c._default_arguments_from_docstring(
451 451 '\n Minuit.migrad(self, int ncall=10000, resume=True, int nsplit=1)\n')
452 452 nt.assert_equal(kwd, ['ncall', 'resume', 'nsplit'])
453 453
454 454 def test_line_magics():
455 455 ip = get_ipython()
456 456 c = ip.Completer
457 457 s, matches = c.complete(None, 'lsmag')
458 458 nt.assert_in('%lsmagic', matches)
459 459 s, matches = c.complete(None, '%lsmag')
460 460 nt.assert_in('%lsmagic', matches)
461 461
462 462
463 463 def test_cell_magics():
464 464 from IPython.core.magic import register_cell_magic
465 465
466 466 @register_cell_magic
467 467 def _foo_cellm(line, cell):
468 468 pass
469 469
470 470 ip = get_ipython()
471 471 c = ip.Completer
472 472
473 473 s, matches = c.complete(None, '_foo_ce')
474 474 nt.assert_in('%%_foo_cellm', matches)
475 475 s, matches = c.complete(None, '%%_foo_ce')
476 476 nt.assert_in('%%_foo_cellm', matches)
477 477
478 478
479 479 def test_line_cell_magics():
480 480 from IPython.core.magic import register_line_cell_magic
481 481
482 482 @register_line_cell_magic
483 483 def _bar_cellm(line, cell):
484 484 pass
485 485
486 486 ip = get_ipython()
487 487 c = ip.Completer
488 488
489 489 # The policy here is trickier, see comments in completion code. The
490 490 # returned values depend on whether the user passes %% or not explicitly,
491 491 # and this will show a difference if the same name is both a line and cell
492 492 # magic.
493 493 s, matches = c.complete(None, '_bar_ce')
494 494 nt.assert_in('%_bar_cellm', matches)
495 495 nt.assert_in('%%_bar_cellm', matches)
496 496 s, matches = c.complete(None, '%_bar_ce')
497 497 nt.assert_in('%_bar_cellm', matches)
498 498 nt.assert_in('%%_bar_cellm', matches)
499 499 s, matches = c.complete(None, '%%_bar_ce')
500 500 nt.assert_not_in('%_bar_cellm', matches)
501 501 nt.assert_in('%%_bar_cellm', matches)
502 502
503 503
504 504 def test_magic_completion_order():
505 505
506 506 ip = get_ipython()
507 507 c = ip.Completer
508 508
509 509 # Test ordering of magics and non-magics with the same name
510 510 # We want the non-magic first
511 511
512 512 # Before importing matplotlib, there should only be one option:
513 513
514 514 text, matches = c.complete('mat')
515 515 nt.assert_equal(matches, ["%matplotlib"])
516 516
517 517
518 518 ip.run_cell("matplotlib = 1") # introduce name into namespace
519 519
520 520 # After the import, there should be two options, ordered like this:
521 521 text, matches = c.complete('mat')
522 522 nt.assert_equal(matches, ["matplotlib", "%matplotlib"])
523 523
524 524
525 525 ip.run_cell("timeit = 1") # define a user variable called 'timeit'
526 526
527 527 # Order of user variable and line and cell magics with same name:
528 528 text, matches = c.complete('timeit')
529 nt.assert_equal(matches, ["timeit", "%timeit","%%timeit"])
529 nt.assert_equal(matches, ["timeit", "%timeit", "%%timeit"])
530
531 def test_match_dict_keys():
532 """
533 Test that match_dict_keys works on a couple of use case does return what
534 expected, and does not crash
535 """
536 delims = ' \t\n`!@#$^&*()=+[{]}\\|;:\'",<>?'
537
538
539 keys = ['foo', b'far']
540 assert match_dict_keys(keys, "b'", delims=delims) == ("'", 2 ,['far'])
541 assert match_dict_keys(keys, "b'f", delims=delims) == ("'", 2 ,['far'])
542 assert match_dict_keys(keys, 'b"', delims=delims) == ('"', 2 ,['far'])
543 assert match_dict_keys(keys, 'b"f', delims=delims) == ('"', 2 ,['far'])
544
545 assert match_dict_keys(keys, "'", delims=delims) == ("'", 1 ,['foo'])
546 assert match_dict_keys(keys, "'f", delims=delims) == ("'", 1 ,['foo'])
547 assert match_dict_keys(keys, '"', delims=delims) == ('"', 1 ,['foo'])
548 assert match_dict_keys(keys, '"f', delims=delims) == ('"', 1 ,['foo'])
549
550 match_dict_keys
530 551
531 552
532 553 def test_dict_key_completion_string():
533 554 """Test dictionary key completion for string keys"""
534 555 ip = get_ipython()
535 556 complete = ip.Completer.complete
536 557
537 558 ip.user_ns['d'] = {'abc': None}
538 559
539 560 # check completion at different stages
540 561 _, matches = complete(line_buffer="d[")
541 562 nt.assert_in("'abc'", matches)
542 563 nt.assert_not_in("'abc']", matches)
543 564
544 565 _, matches = complete(line_buffer="d['")
545 566 nt.assert_in("abc", matches)
546 567 nt.assert_not_in("abc']", matches)
547 568
548 569 _, matches = complete(line_buffer="d['a")
549 570 nt.assert_in("abc", matches)
550 571 nt.assert_not_in("abc']", matches)
551 572
552 573 # check use of different quoting
553 574 _, matches = complete(line_buffer="d[\"")
554 575 nt.assert_in("abc", matches)
555 576 nt.assert_not_in('abc\"]', matches)
556 577
557 578 _, matches = complete(line_buffer="d[\"a")
558 579 nt.assert_in("abc", matches)
559 580 nt.assert_not_in('abc\"]', matches)
560 581
561 582 # check sensitivity to following context
562 583 _, matches = complete(line_buffer="d[]", cursor_pos=2)
563 584 nt.assert_in("'abc'", matches)
564 585
565 586 _, matches = complete(line_buffer="d['']", cursor_pos=3)
566 587 nt.assert_in("abc", matches)
567 588 nt.assert_not_in("abc'", matches)
568 589 nt.assert_not_in("abc']", matches)
569 590
570 591 # check multiple solutions are correctly returned and that noise is not
571 592 ip.user_ns['d'] = {'abc': None, 'abd': None, 'bad': None, object(): None,
572 593 5: None}
573 594
574 595 _, matches = complete(line_buffer="d['a")
575 596 nt.assert_in("abc", matches)
576 597 nt.assert_in("abd", matches)
577 598 nt.assert_not_in("bad", matches)
578 599 assert not any(m.endswith((']', '"', "'")) for m in matches), matches
579 600
580 601 # check escaping and whitespace
581 602 ip.user_ns['d'] = {'a\nb': None, 'a\'b': None, 'a"b': None, 'a word': None}
582 603 _, matches = complete(line_buffer="d['a")
583 604 nt.assert_in("a\\nb", matches)
584 605 nt.assert_in("a\\'b", matches)
585 606 nt.assert_in("a\"b", matches)
586 607 nt.assert_in("a word", matches)
587 608 assert not any(m.endswith((']', '"', "'")) for m in matches), matches
588 609
589 610 # - can complete on non-initial word of the string
590 611 _, matches = complete(line_buffer="d['a w")
591 612 nt.assert_in("word", matches)
592 613
593 614 # - understands quote escaping
594 615 _, matches = complete(line_buffer="d['a\\'")
595 616 nt.assert_in("b", matches)
596 617
597 618 # - default quoting should work like repr
598 619 _, matches = complete(line_buffer="d[")
599 620 nt.assert_in("\"a'b\"", matches)
600 621
601 622 # - when opening quote with ", possible to match with unescaped apostrophe
602 623 _, matches = complete(line_buffer="d[\"a'")
603 624 nt.assert_in("b", matches)
604 625
605 626 # need to not split at delims that readline won't split at
606 627 if '-' not in ip.Completer.splitter.delims:
607 628 ip.user_ns['d'] = {'before-after': None}
608 629 _, matches = complete(line_buffer="d['before-af")
609 630 nt.assert_in('before-after', matches)
610 631
611 632 def test_dict_key_completion_contexts():
612 633 """Test expression contexts in which dict key completion occurs"""
613 634 ip = get_ipython()
614 635 complete = ip.Completer.complete
615 636 d = {'abc': None}
616 637 ip.user_ns['d'] = d
617 638
618 639 class C:
619 640 data = d
620 641 ip.user_ns['C'] = C
621 642 ip.user_ns['get'] = lambda: d
622 643
623 644 def assert_no_completion(**kwargs):
624 645 _, matches = complete(**kwargs)
625 646 nt.assert_not_in('abc', matches)
626 647 nt.assert_not_in('abc\'', matches)
627 648 nt.assert_not_in('abc\']', matches)
628 649 nt.assert_not_in('\'abc\'', matches)
629 650 nt.assert_not_in('\'abc\']', matches)
630 651
631 652 def assert_completion(**kwargs):
632 653 _, matches = complete(**kwargs)
633 654 nt.assert_in("'abc'", matches)
634 655 nt.assert_not_in("'abc']", matches)
635 656
636 657 # no completion after string closed, even if reopened
637 658 assert_no_completion(line_buffer="d['a'")
638 659 assert_no_completion(line_buffer="d[\"a\"")
639 660 assert_no_completion(line_buffer="d['a' + ")
640 661 assert_no_completion(line_buffer="d['a' + '")
641 662
642 663 # completion in non-trivial expressions
643 664 assert_completion(line_buffer="+ d[")
644 665 assert_completion(line_buffer="(d[")
645 666 assert_completion(line_buffer="C.data[")
646 667
647 668 # greedy flag
648 669 def assert_completion(**kwargs):
649 670 _, matches = complete(**kwargs)
650 671 nt.assert_in("get()['abc']", matches)
651 672
652 673 assert_no_completion(line_buffer="get()[")
653 674 with greedy_completion():
654 675 assert_completion(line_buffer="get()[")
655 676 assert_completion(line_buffer="get()['")
656 677 assert_completion(line_buffer="get()['a")
657 678 assert_completion(line_buffer="get()['ab")
658 679 assert_completion(line_buffer="get()['abc")
659 680
660 681
661 682
662 683 def test_dict_key_completion_bytes():
663 684 """Test handling of bytes in dict key completion"""
664 685 ip = get_ipython()
665 686 complete = ip.Completer.complete
666 687
667 688 ip.user_ns['d'] = {'abc': None, b'abd': None}
668 689
669 690 _, matches = complete(line_buffer="d[")
670 691 nt.assert_in("'abc'", matches)
671 692 nt.assert_in("b'abd'", matches)
672 693
673 694 if False: # not currently implemented
674 695 _, matches = complete(line_buffer="d[b")
675 696 nt.assert_in("b'abd'", matches)
676 697 nt.assert_not_in("b'abc'", matches)
677 698
678 699 _, matches = complete(line_buffer="d[b'")
679 700 nt.assert_in("abd", matches)
680 701 nt.assert_not_in("abc", matches)
681 702
682 703 _, matches = complete(line_buffer="d[B'")
683 704 nt.assert_in("abd", matches)
684 705 nt.assert_not_in("abc", matches)
685 706
686 707 _, matches = complete(line_buffer="d['")
687 708 nt.assert_in("abc", matches)
688 709 nt.assert_not_in("abd", matches)
689 710
690 711
691 712 def test_dict_key_completion_unicode_py3():
692 713 """Test handling of unicode in dict key completion"""
693 714 ip = get_ipython()
694 715 complete = ip.Completer.complete
695 716
696 717 ip.user_ns['d'] = {u'a\u05d0': None}
697 718
698 719 # query using escape
699 720 if sys.platform != 'win32':
700 721 # Known failure on Windows
701 722 _, matches = complete(line_buffer="d['a\\u05d0")
702 723 nt.assert_in("u05d0", matches) # tokenized after \\
703 724
704 725 # query using character
705 726 _, matches = complete(line_buffer="d['a\u05d0")
706 727 nt.assert_in(u"a\u05d0", matches)
707 728
708 729 with greedy_completion():
709 730 # query using escape
710 731 _, matches = complete(line_buffer="d['a\\u05d0")
711 732 nt.assert_in("d['a\\u05d0']", matches) # tokenized after \\
712 733
713 734 # query using character
714 735 _, matches = complete(line_buffer="d['a\u05d0")
715 736 nt.assert_in(u"d['a\u05d0']", matches)
716 737
717 738
718 739
719 740 @dec.skip_without('numpy')
720 741 def test_struct_array_key_completion():
721 742 """Test dict key completion applies to numpy struct arrays"""
722 743 import numpy
723 744 ip = get_ipython()
724 745 complete = ip.Completer.complete
725 746 ip.user_ns['d'] = numpy.array([], dtype=[('hello', 'f'), ('world', 'f')])
726 747 _, matches = complete(line_buffer="d['")
727 748 nt.assert_in("hello", matches)
728 749 nt.assert_in("world", matches)
729 750 # complete on the numpy struct itself
730 751 dt = numpy.dtype([('my_head', [('my_dt', '>u4'), ('my_df', '>u4')]),
731 752 ('my_data', '>f4', 5)])
732 753 x = numpy.zeros(2, dtype=dt)
733 754 ip.user_ns['d'] = x[1]
734 755 _, matches = complete(line_buffer="d['")
735 756 nt.assert_in("my_head", matches)
736 757 nt.assert_in("my_data", matches)
737 758 # complete on a nested level
738 759 with greedy_completion():
739 760 ip.user_ns['d'] = numpy.zeros(2, dtype=dt)
740 761 _, matches = complete(line_buffer="d[1]['my_head']['")
741 762 nt.assert_true(any(["my_dt" in m for m in matches]))
742 763 nt.assert_true(any(["my_df" in m for m in matches]))
743 764
744 765
745 766 @dec.skip_without('pandas')
746 767 def test_dataframe_key_completion():
747 768 """Test dict key completion applies to pandas DataFrames"""
748 769 import pandas
749 770 ip = get_ipython()
750 771 complete = ip.Completer.complete
751 772 ip.user_ns['d'] = pandas.DataFrame({'hello': [1], 'world': [2]})
752 773 _, matches = complete(line_buffer="d['")
753 774 nt.assert_in("hello", matches)
754 775 nt.assert_in("world", matches)
755 776
756 777
757 778 def test_dict_key_completion_invalids():
758 779 """Smoke test cases dict key completion can't handle"""
759 780 ip = get_ipython()
760 781 complete = ip.Completer.complete
761 782
762 783 ip.user_ns['no_getitem'] = None
763 784 ip.user_ns['no_keys'] = []
764 785 ip.user_ns['cant_call_keys'] = dict
765 786 ip.user_ns['empty'] = {}
766 787 ip.user_ns['d'] = {'abc': 5}
767 788
768 789 _, matches = complete(line_buffer="no_getitem['")
769 790 _, matches = complete(line_buffer="no_keys['")
770 791 _, matches = complete(line_buffer="cant_call_keys['")
771 792 _, matches = complete(line_buffer="empty['")
772 793 _, matches = complete(line_buffer="name_error['")
773 794 _, matches = complete(line_buffer="d['\\") # incomplete escape
774 795
775 796 class KeyCompletable(object):
776 797 def __init__(self, things=()):
777 798 self.things = things
778 799
779 800 def _ipython_key_completions_(self):
780 801 return list(self.things)
781 802
782 803 def test_object_key_completion():
783 804 ip = get_ipython()
784 805 ip.user_ns['key_completable'] = KeyCompletable(['qwerty', 'qwick'])
785 806
786 807 _, matches = ip.Completer.complete(line_buffer="key_completable['qw")
787 808 nt.assert_in('qwerty', matches)
788 809 nt.assert_in('qwick', matches)
789 810
790 811
791 812 def test_tryimport():
792 813 """
793 814 Test that try-import don't crash on trailing dot, and import modules before
794 815 """
795 816 from IPython.core.completerlib import try_import
796 817 assert(try_import("IPython."))
797 818
798 819
799 820 def test_aimport_module_completer():
800 821 ip = get_ipython()
801 822 _, matches = ip.complete('i', '%aimport i')
802 823 nt.assert_in('io', matches)
803 824 nt.assert_not_in('int', matches)
804 825
805 826 def test_nested_import_module_completer():
806 827 ip = get_ipython()
807 828 _, matches = ip.complete(None, 'import IPython.co', 17)
808 829 nt.assert_in('IPython.core', matches)
809 830 nt.assert_not_in('import IPython.core', matches)
810 831 nt.assert_not_in('IPython.display', matches)
811 832
812 833 def test_import_module_completer():
813 834 ip = get_ipython()
814 835 _, matches = ip.complete('i', 'import i')
815 836 nt.assert_in('io', matches)
816 837 nt.assert_not_in('int', matches)
817 838
818 839 def test_from_module_completer():
819 840 ip = get_ipython()
820 841 _, matches = ip.complete('B', 'from io import B', 16)
821 842 nt.assert_in('BytesIO', matches)
822 843 nt.assert_not_in('BaseException', matches)
General Comments 0
You need to be logged in to leave comments. Login now