##// END OF EJS Templates
use function, and tests
Matthias Bussonnier -
Show More
@@ -1,1267 +1,1266 b''
1 1 # encoding: utf-8
2 2 """Word completion for IPython.
3 3
4 4 This module is a 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, but we need a lot more
7 7 functionality specific to IPython, so this module will continue to live as an
8 8 IPython-specific utility.
9 9
10 10 Original rlcompleter documentation:
11 11
12 12 This requires the latest extension to the readline module (the
13 13 completes keywords, built-ins and globals in __main__; when completing
14 14 NAME.NAME..., it evaluates (!) the expression up to the last dot and
15 15 completes its attributes.
16 16
17 17 It's very cool to do "import string" type "string.", hit the
18 18 completion key (twice), and see the list of names defined by the
19 19 string module!
20 20
21 21 Tip: to use the tab key as the completion key, call
22 22
23 23 readline.parse_and_bind("tab: complete")
24 24
25 25 Notes:
26 26
27 27 - Exceptions raised by the completer function are *ignored* (and
28 28 generally cause the completion to fail). This is a feature -- since
29 29 readline sets the tty device in raw (or cbreak) mode, printing a
30 30 traceback wouldn't work well without some complicated hoopla to save,
31 31 reset and restore the tty state.
32 32
33 33 - The evaluation of the NAME.NAME... form may cause arbitrary
34 34 application defined code to be executed if an object with a
35 35 ``__getattr__`` hook is found. Since it is the responsibility of the
36 36 application (or the user) to enable this feature, I consider this an
37 37 acceptable risk. More complicated expressions (e.g. function calls or
38 38 indexing operations) are *not* evaluated.
39 39
40 40 - GNU readline is also used by the built-in functions input() and
41 41 raw_input(), and thus these also benefit/suffer from the completer
42 42 features. Clearly an interactive application can benefit by
43 43 specifying its own completer function and using raw_input() for all
44 44 its input.
45 45
46 46 - When the original stdin is not a tty device, GNU readline is never
47 47 used, and this module (and the readline module) are silently inactive.
48 48 """
49 49
50 50 # Copyright (c) IPython Development Team.
51 51 # Distributed under the terms of the Modified BSD License.
52 52 #
53 53 # Some of this code originated from rlcompleter in the Python standard library
54 54 # Copyright (C) 2001 Python Software Foundation, www.python.org
55 55
56 56 import __main__
57 57 import glob
58 58 import inspect
59 59 import itertools
60 60 import keyword
61 61 import os
62 62 import re
63 63 import sys
64 64 import unicodedata
65 65 import string
66 66
67 67 from IPython.config.configurable import Configurable
68 68 from IPython.core.error import TryNext
69 69 from IPython.core.inputsplitter import ESC_MAGIC
70 70 from IPython.core.latex_symbols import latex_symbols, reverse_latex_symbol
71 71 from IPython.utils import generics
72 72 from IPython.utils import io
73 73 from IPython.utils.decorators import undoc
74 74 from IPython.utils.dir2 import dir2
75 75 from IPython.utils.process import arg_split
76 76 from IPython.utils.py3compat import builtin_mod, string_types, PY3
77 77 from IPython.utils.traitlets import CBool, Enum
78 78
79 79 #-----------------------------------------------------------------------------
80 80 # Globals
81 81 #-----------------------------------------------------------------------------
82 82
83 83 # Public API
84 84 __all__ = ['Completer','IPCompleter']
85 85
86 86 if sys.platform == 'win32':
87 87 PROTECTABLES = ' '
88 88 else:
89 89 PROTECTABLES = ' ()[]{}?=\\|;:\'#*"^&'
90 90
91 91
92 92 #-----------------------------------------------------------------------------
93 93 # Main functions and classes
94 94 #-----------------------------------------------------------------------------
95 95
96 96 def has_open_quotes(s):
97 97 """Return whether a string has open quotes.
98 98
99 99 This simply counts whether the number of quote characters of either type in
100 100 the string is odd.
101 101
102 102 Returns
103 103 -------
104 104 If there is an open quote, the quote character is returned. Else, return
105 105 False.
106 106 """
107 107 # We check " first, then ', so complex cases with nested quotes will get
108 108 # the " to take precedence.
109 109 if s.count('"') % 2:
110 110 return '"'
111 111 elif s.count("'") % 2:
112 112 return "'"
113 113 else:
114 114 return False
115 115
116 116
117 117 def protect_filename(s):
118 118 """Escape a string to protect certain characters."""
119 119
120 120 return "".join([(ch in PROTECTABLES and '\\' + ch or ch)
121 121 for ch in s])
122 122
123 123 def expand_user(path):
124 124 """Expand '~'-style usernames in strings.
125 125
126 126 This is similar to :func:`os.path.expanduser`, but it computes and returns
127 127 extra information that will be useful if the input was being used in
128 128 computing completions, and you wish to return the completions with the
129 129 original '~' instead of its expanded value.
130 130
131 131 Parameters
132 132 ----------
133 133 path : str
134 134 String to be expanded. If no ~ is present, the output is the same as the
135 135 input.
136 136
137 137 Returns
138 138 -------
139 139 newpath : str
140 140 Result of ~ expansion in the input path.
141 141 tilde_expand : bool
142 142 Whether any expansion was performed or not.
143 143 tilde_val : str
144 144 The value that ~ was replaced with.
145 145 """
146 146 # Default values
147 147 tilde_expand = False
148 148 tilde_val = ''
149 149 newpath = path
150 150
151 151 if path.startswith('~'):
152 152 tilde_expand = True
153 153 rest = len(path)-1
154 154 newpath = os.path.expanduser(path)
155 155 if rest:
156 156 tilde_val = newpath[:-rest]
157 157 else:
158 158 tilde_val = newpath
159 159
160 160 return newpath, tilde_expand, tilde_val
161 161
162 162
163 163 def compress_user(path, tilde_expand, tilde_val):
164 164 """Does the opposite of expand_user, with its outputs.
165 165 """
166 166 if tilde_expand:
167 167 return path.replace(tilde_val, '~')
168 168 else:
169 169 return path
170 170
171 171
172 172
173 173 def penalize_magics_key(word):
174 174 """key for sorting that penalizes magic commands in the ordering
175 175
176 176 Normal words are left alone.
177 177
178 178 Magic commands have the initial % moved to the end, e.g.
179 179 %matplotlib is transformed as follows:
180 180
181 181 %matplotlib -> matplotlib%
182 182
183 183 [The choice of the final % is arbitrary.]
184 184
185 185 Since "matplotlib" < "matplotlib%" as strings,
186 186 "timeit" will appear before the magic "%timeit" in the ordering
187 187
188 188 For consistency, move "%%" to the end, so cell magics appear *after*
189 189 line magics with the same name.
190 190
191 191 A check is performed that there are no other "%" in the string;
192 192 if there are, then the string is not a magic command and is left unchanged.
193 193
194 194 """
195 195
196 196 # Move any % signs from start to end of the key
197 197 # provided there are no others elsewhere in the string
198 198
199 199 if word[:2] == "%%":
200 200 if not "%" in word[2:]:
201 201 return word[2:] + "%%"
202 202
203 203 if word[:1] == "%":
204 204 if not "%" in word[1:]:
205 205 return word[1:] + "%"
206 206
207 207 return word
208 208
209 209
210 210 @undoc
211 211 class Bunch(object): pass
212 212
213 213
214 214 DELIMS = ' \t\n`!@#$^&*()=+[{]}\\|;:\'",<>?'
215 215 GREEDY_DELIMS = ' =\r\n'
216 216
217 217
218 218 class CompletionSplitter(object):
219 219 """An object to split an input line in a manner similar to readline.
220 220
221 221 By having our own implementation, we can expose readline-like completion in
222 222 a uniform manner to all frontends. This object only needs to be given the
223 223 line of text to be split and the cursor position on said line, and it
224 224 returns the 'word' to be completed on at the cursor after splitting the
225 225 entire line.
226 226
227 227 What characters are used as splitting delimiters can be controlled by
228 228 setting the `delims` attribute (this is a property that internally
229 229 automatically builds the necessary regular expression)"""
230 230
231 231 # Private interface
232 232
233 233 # A string of delimiter characters. The default value makes sense for
234 234 # IPython's most typical usage patterns.
235 235 _delims = DELIMS
236 236
237 237 # The expression (a normal string) to be compiled into a regular expression
238 238 # for actual splitting. We store it as an attribute mostly for ease of
239 239 # debugging, since this type of code can be so tricky to debug.
240 240 _delim_expr = None
241 241
242 242 # The regular expression that does the actual splitting
243 243 _delim_re = None
244 244
245 245 def __init__(self, delims=None):
246 246 delims = CompletionSplitter._delims if delims is None else delims
247 247 self.delims = delims
248 248
249 249 @property
250 250 def delims(self):
251 251 """Return the string of delimiter characters."""
252 252 return self._delims
253 253
254 254 @delims.setter
255 255 def delims(self, delims):
256 256 """Set the delimiters for line splitting."""
257 257 expr = '[' + ''.join('\\'+ c for c in delims) + ']'
258 258 self._delim_re = re.compile(expr)
259 259 self._delims = delims
260 260 self._delim_expr = expr
261 261
262 262 def split_line(self, line, cursor_pos=None):
263 263 """Split a line of text with a cursor at the given position.
264 264 """
265 265 l = line if cursor_pos is None else line[:cursor_pos]
266 266 return self._delim_re.split(l)[-1]
267 267
268 268
269 269 class Completer(Configurable):
270 270
271 271 greedy = CBool(False, config=True,
272 272 help="""Activate greedy completion
273 273
274 274 This will enable completion on elements of lists, results of function calls, etc.,
275 275 but can be unsafe because the code is actually evaluated on TAB.
276 276 """
277 277 )
278 278
279 279
280 280 def __init__(self, namespace=None, global_namespace=None, **kwargs):
281 281 """Create a new completer for the command line.
282 282
283 283 Completer(namespace=ns,global_namespace=ns2) -> completer instance.
284 284
285 285 If unspecified, the default namespace where completions are performed
286 286 is __main__ (technically, __main__.__dict__). Namespaces should be
287 287 given as dictionaries.
288 288
289 289 An optional second namespace can be given. This allows the completer
290 290 to handle cases where both the local and global scopes need to be
291 291 distinguished.
292 292
293 293 Completer instances should be used as the completion mechanism of
294 294 readline via the set_completer() call:
295 295
296 296 readline.set_completer(Completer(my_namespace).complete)
297 297 """
298 298
299 299 # Don't bind to namespace quite yet, but flag whether the user wants a
300 300 # specific namespace or to use __main__.__dict__. This will allow us
301 301 # to bind to __main__.__dict__ at completion time, not now.
302 302 if namespace is None:
303 303 self.use_main_ns = 1
304 304 else:
305 305 self.use_main_ns = 0
306 306 self.namespace = namespace
307 307
308 308 # The global namespace, if given, can be bound directly
309 309 if global_namespace is None:
310 310 self.global_namespace = {}
311 311 else:
312 312 self.global_namespace = global_namespace
313 313
314 314 super(Completer, self).__init__(**kwargs)
315 315
316 316 def complete(self, text, state):
317 317 """Return the next possible completion for 'text'.
318 318
319 319 This is called successively with state == 0, 1, 2, ... until it
320 320 returns None. The completion should begin with 'text'.
321 321
322 322 """
323 323 if self.use_main_ns:
324 324 self.namespace = __main__.__dict__
325 325
326 326 if state == 0:
327 327 if "." in text:
328 328 self.matches = self.attr_matches(text)
329 329 else:
330 330 self.matches = self.global_matches(text)
331 331 try:
332 332 return self.matches[state]
333 333 except IndexError:
334 334 return None
335 335
336 336 def global_matches(self, text):
337 337 """Compute matches when text is a simple name.
338 338
339 339 Return a list of all keywords, built-in functions and names currently
340 340 defined in self.namespace or self.global_namespace that match.
341 341
342 342 """
343 343 #print 'Completer->global_matches, txt=%r' % text # dbg
344 344 matches = []
345 345 match_append = matches.append
346 346 n = len(text)
347 347 for lst in [keyword.kwlist,
348 348 builtin_mod.__dict__.keys(),
349 349 self.namespace.keys(),
350 350 self.global_namespace.keys()]:
351 351 for word in lst:
352 352 if word[:n] == text and word != "__builtins__":
353 353 match_append(word)
354 354 return matches
355 355
356 356 def attr_matches(self, text):
357 357 """Compute matches when text contains a dot.
358 358
359 359 Assuming the text is of the form NAME.NAME....[NAME], and is
360 360 evaluatable in self.namespace or self.global_namespace, it will be
361 361 evaluated and its attributes (as revealed by dir()) are used as
362 362 possible completions. (For class instances, class members are are
363 363 also considered.)
364 364
365 365 WARNING: this can still invoke arbitrary C code, if an object
366 366 with a __getattr__ hook is evaluated.
367 367
368 368 """
369 369
370 370 #io.rprint('Completer->attr_matches, txt=%r' % text) # dbg
371 371 # Another option, seems to work great. Catches things like ''.<tab>
372 372 m = re.match(r"(\S+(\.\w+)*)\.(\w*)$", text)
373 373
374 374 if m:
375 375 expr, attr = m.group(1, 3)
376 376 elif self.greedy:
377 377 m2 = re.match(r"(.+)\.(\w*)$", self.line_buffer)
378 378 if not m2:
379 379 return []
380 380 expr, attr = m2.group(1,2)
381 381 else:
382 382 return []
383 383
384 384 try:
385 385 obj = eval(expr, self.namespace)
386 386 except:
387 387 try:
388 388 obj = eval(expr, self.global_namespace)
389 389 except:
390 390 return []
391 391
392 392 if self.limit_to__all__ and hasattr(obj, '__all__'):
393 393 words = get__all__entries(obj)
394 394 else:
395 395 words = dir2(obj)
396 396
397 397 try:
398 398 words = generics.complete_object(obj, words)
399 399 except TryNext:
400 400 pass
401 401 except Exception:
402 402 # Silence errors from completion function
403 403 #raise # dbg
404 404 pass
405 405 # Build match list to return
406 406 n = len(attr)
407 407 res = ["%s.%s" % (expr, w) for w in words if w[:n] == attr ]
408 408 return res
409 409
410 410
411 411 def get__all__entries(obj):
412 412 """returns the strings in the __all__ attribute"""
413 413 try:
414 414 words = getattr(obj, '__all__')
415 415 except:
416 416 return []
417 417
418 418 return [w for w in words if isinstance(w, string_types)]
419 419
420 420
421 421 def match_dict_keys(keys, prefix):
422 422 """Used by dict_key_matches, matching the prefix to a list of keys"""
423 423 if not prefix:
424 424 return None, 0, [repr(k) for k in keys
425 425 if isinstance(k, (string_types, bytes))]
426 426 quote_match = re.search('["\']', prefix)
427 427 quote = quote_match.group()
428 428 try:
429 429 prefix_str = eval(prefix + quote, {})
430 430 except Exception:
431 431 return None, 0, []
432 432
433 433 token_match = re.search(r'\w*$', prefix, re.UNICODE)
434 434 token_start = token_match.start()
435 435 token_prefix = token_match.group()
436 436
437 437 # TODO: support bytes in Py3k
438 438 matched = []
439 439 for key in keys:
440 440 try:
441 441 if not key.startswith(prefix_str):
442 442 continue
443 443 except (AttributeError, TypeError, UnicodeError):
444 444 # Python 3+ TypeError on b'a'.startswith('a') or vice-versa
445 445 continue
446 446
447 447 # reformat remainder of key to begin with prefix
448 448 rem = key[len(prefix_str):]
449 449 # force repr wrapped in '
450 450 rem_repr = repr(rem + '"')
451 451 if rem_repr.startswith('u') and prefix[0] not in 'uU':
452 452 # Found key is unicode, but prefix is Py2 string.
453 453 # Therefore attempt to interpret key as string.
454 454 try:
455 455 rem_repr = repr(rem.encode('ascii') + '"')
456 456 except UnicodeEncodeError:
457 457 continue
458 458
459 459 rem_repr = rem_repr[1 + rem_repr.index("'"):-2]
460 460 if quote == '"':
461 461 # The entered prefix is quoted with ",
462 462 # but the match is quoted with '.
463 463 # A contained " hence needs escaping for comparison:
464 464 rem_repr = rem_repr.replace('"', '\\"')
465 465
466 466 # then reinsert prefix from start of token
467 467 matched.append('%s%s' % (token_prefix, rem_repr))
468 468 return quote, token_start, matched
469 469
470 470
471 471 def _safe_isinstance(obj, module, class_name):
472 472 """Checks if obj is an instance of module.class_name if loaded
473 473 """
474 474 return (module in sys.modules and
475 475 isinstance(obj, getattr(__import__(module), class_name)))
476 476
477 477
478 478
479 def back_unicode_name_matches(text):
480 u"""Match unicode characters back to unicode name
481
482 This does β˜ƒ -> \\snowman
483
484 Note that snowman is not a valid python3 combining character but will be expanded.
485 Though it will not recombine back to the snowman character by the completion machinery.
486
487 This will not either back-complete standard sequences like \n, \b ...
488
489 Used on Python 3 only.
490 """
491 if len(text)<2:
492 return u'', ()
493 maybe_slash = text[-2]
494 if maybe_slash != '\\':
495 return u'', ()
496
497 char = text[-1]
498 # no expand on quote for completion in strings.
499 # nor backcomplete standard ascii keys
500 if char in string.ascii_letters or char in ['"',"'"]:
501 return u'', ()
502 try :
503 unic = unicodedata.name(char)
504 return '\\'+char,['\\'+unic]
505 except KeyError as e:
506 pass
507 return u'', ()
508
509 def back_latex_name_matches(text):
510 u"""Match latex characters back to unicode name
511
512 This does ->\\sqrt
513
514 Used on Python 3 only.
515 """
516 if len(text)<2:
517 return u'', ()
518 maybe_slash = text[-2]
519 if maybe_slash != '\\':
520 return u'', ()
521
522
523 char = text[-1]
524 # no expand on quote for completion in strings.
525 # nor backcomplete standard ascii keys
526 if char in string.ascii_letters or char in ['"',"'"]:
527 return u'', ()
528 try :
529 latex = reverse_latex_symbol[char]
530 # '\\' replace the \ as well
531 return '\\'+char,[latex]
532 except KeyError as e:
533 pass
534 return u'', ()
535
536
479 537 class IPCompleter(Completer):
480 538 """Extension of the completer class with IPython-specific features"""
481 539
482 540 def _greedy_changed(self, name, old, new):
483 541 """update the splitter and readline delims when greedy is changed"""
484 542 if new:
485 543 self.splitter.delims = GREEDY_DELIMS
486 544 else:
487 545 self.splitter.delims = DELIMS
488 546
489 547 if self.readline:
490 548 self.readline.set_completer_delims(self.splitter.delims)
491 549
492 550 merge_completions = CBool(True, config=True,
493 551 help="""Whether to merge completion results into a single list
494 552
495 553 If False, only the completion results from the first non-empty
496 554 completer will be returned.
497 555 """
498 556 )
499 557 omit__names = Enum((0,1,2), default_value=2, config=True,
500 558 help="""Instruct the completer to omit private method names
501 559
502 560 Specifically, when completing on ``object.<tab>``.
503 561
504 562 When 2 [default]: all names that start with '_' will be excluded.
505 563
506 564 When 1: all 'magic' names (``__foo__``) will be excluded.
507 565
508 566 When 0: nothing will be excluded.
509 567 """
510 568 )
511 569 limit_to__all__ = CBool(default_value=False, config=True,
512 570 help="""Instruct the completer to use __all__ for the completion
513 571
514 572 Specifically, when completing on ``object.<tab>``.
515 573
516 574 When True: only those names in obj.__all__ will be included.
517 575
518 576 When False [default]: the __all__ attribute is ignored
519 577 """
520 578 )
521 579
522 580 def __init__(self, shell=None, namespace=None, global_namespace=None,
523 581 use_readline=True, config=None, **kwargs):
524 582 """IPCompleter() -> completer
525 583
526 584 Return a completer object suitable for use by the readline library
527 585 via readline.set_completer().
528 586
529 587 Inputs:
530 588
531 589 - shell: a pointer to the ipython shell itself. This is needed
532 590 because this completer knows about magic functions, and those can
533 591 only be accessed via the ipython instance.
534 592
535 593 - namespace: an optional dict where completions are performed.
536 594
537 595 - global_namespace: secondary optional dict for completions, to
538 596 handle cases (such as IPython embedded inside functions) where
539 597 both Python scopes are visible.
540 598
541 599 use_readline : bool, optional
542 600 If true, use the readline library. This completer can still function
543 601 without readline, though in that case callers must provide some extra
544 602 information on each call about the current line."""
545 603
546 604 self.magic_escape = ESC_MAGIC
547 605 self.splitter = CompletionSplitter()
548 606
549 607 # Readline configuration, only used by the rlcompleter method.
550 608 if use_readline:
551 609 # We store the right version of readline so that later code
552 610 import IPython.utils.rlineimpl as readline
553 611 self.readline = readline
554 612 else:
555 613 self.readline = None
556 614
557 615 # _greedy_changed() depends on splitter and readline being defined:
558 616 Completer.__init__(self, namespace=namespace, global_namespace=global_namespace,
559 617 config=config, **kwargs)
560 618
561 619 # List where completion matches will be stored
562 620 self.matches = []
563 621 self.shell = shell
564 622 # Regexp to split filenames with spaces in them
565 623 self.space_name_re = re.compile(r'([^\\] )')
566 624 # Hold a local ref. to glob.glob for speed
567 625 self.glob = glob.glob
568 626
569 627 # Determine if we are running on 'dumb' terminals, like (X)Emacs
570 628 # buffers, to avoid completion problems.
571 629 term = os.environ.get('TERM','xterm')
572 630 self.dumb_terminal = term in ['dumb','emacs']
573 631
574 632 # Special handling of backslashes needed in win32 platforms
575 633 if sys.platform == "win32":
576 634 self.clean_glob = self._clean_glob_win32
577 635 else:
578 636 self.clean_glob = self._clean_glob
579 637
580 638 #regexp to parse docstring for function signature
581 639 self.docstring_sig_re = re.compile(r'^[\w|\s.]+\(([^)]*)\).*')
582 640 self.docstring_kwd_re = re.compile(r'[\s|\[]*(\w+)(?:\s*=\s*.*)')
583 641 #use this if positional argument name is also needed
584 642 #= re.compile(r'[\s|\[]*(\w+)(?:\s*=?\s*.*)')
585 643
586 644 # All active matcher routines for completion
587 645 self.matchers = [self.python_matches,
588 646 self.file_matches,
589 647 self.magic_matches,
590 648 self.python_func_kw_matches,
591 649 self.dict_key_matches,
592 650 ]
593 651
594 652 def all_completions(self, text):
595 653 """
596 654 Wrapper around the complete method for the benefit of emacs
597 655 and pydb.
598 656 """
599 657 return self.complete(text)[1]
600 658
601 659 def _clean_glob(self,text):
602 660 return self.glob("%s*" % text)
603 661
604 662 def _clean_glob_win32(self,text):
605 663 return [f.replace("\\","/")
606 664 for f in self.glob("%s*" % text)]
607 665
608 666 def file_matches(self, text):
609 667 """Match filenames, expanding ~USER type strings.
610 668
611 669 Most of the seemingly convoluted logic in this completer is an
612 670 attempt to handle filenames with spaces in them. And yet it's not
613 671 quite perfect, because Python's readline doesn't expose all of the
614 672 GNU readline details needed for this to be done correctly.
615 673
616 674 For a filename with a space in it, the printed completions will be
617 675 only the parts after what's already been typed (instead of the
618 676 full completions, as is normally done). I don't think with the
619 677 current (as of Python 2.3) Python readline it's possible to do
620 678 better."""
621 679
622 680 #io.rprint('Completer->file_matches: <%r>' % text) # dbg
623 681
624 682 # chars that require escaping with backslash - i.e. chars
625 683 # that readline treats incorrectly as delimiters, but we
626 684 # don't want to treat as delimiters in filename matching
627 685 # when escaped with backslash
628 686 if text.startswith('!'):
629 687 text = text[1:]
630 688 text_prefix = '!'
631 689 else:
632 690 text_prefix = ''
633 691
634 692 text_until_cursor = self.text_until_cursor
635 693 # track strings with open quotes
636 694 open_quotes = has_open_quotes(text_until_cursor)
637 695
638 696 if '(' in text_until_cursor or '[' in text_until_cursor:
639 697 lsplit = text
640 698 else:
641 699 try:
642 700 # arg_split ~ shlex.split, but with unicode bugs fixed by us
643 701 lsplit = arg_split(text_until_cursor)[-1]
644 702 except ValueError:
645 703 # typically an unmatched ", or backslash without escaped char.
646 704 if open_quotes:
647 705 lsplit = text_until_cursor.split(open_quotes)[-1]
648 706 else:
649 707 return []
650 708 except IndexError:
651 709 # tab pressed on empty line
652 710 lsplit = ""
653 711
654 712 if not open_quotes and lsplit != protect_filename(lsplit):
655 713 # if protectables are found, do matching on the whole escaped name
656 714 has_protectables = True
657 715 text0,text = text,lsplit
658 716 else:
659 717 has_protectables = False
660 718 text = os.path.expanduser(text)
661 719
662 720 if text == "":
663 721 return [text_prefix + protect_filename(f) for f in self.glob("*")]
664 722
665 723 # Compute the matches from the filesystem
666 724 m0 = self.clean_glob(text.replace('\\',''))
667 725
668 726 if has_protectables:
669 727 # If we had protectables, we need to revert our changes to the
670 728 # beginning of filename so that we don't double-write the part
671 729 # of the filename we have so far
672 730 len_lsplit = len(lsplit)
673 731 matches = [text_prefix + text0 +
674 732 protect_filename(f[len_lsplit:]) for f in m0]
675 733 else:
676 734 if open_quotes:
677 735 # if we have a string with an open quote, we don't need to
678 736 # protect the names at all (and we _shouldn't_, as it
679 737 # would cause bugs when the filesystem call is made).
680 738 matches = m0
681 739 else:
682 740 matches = [text_prefix +
683 741 protect_filename(f) for f in m0]
684 742
685 743 #io.rprint('mm', matches) # dbg
686 744
687 745 # Mark directories in input list by appending '/' to their names.
688 746 matches = [x+'/' if os.path.isdir(x) else x for x in matches]
689 747 return matches
690 748
691 749 def magic_matches(self, text):
692 750 """Match magics"""
693 751 #print 'Completer->magic_matches:',text,'lb',self.text_until_cursor # dbg
694 752 # Get all shell magics now rather than statically, so magics loaded at
695 753 # runtime show up too.
696 754 lsm = self.shell.magics_manager.lsmagic()
697 755 line_magics = lsm['line']
698 756 cell_magics = lsm['cell']
699 757 pre = self.magic_escape
700 758 pre2 = pre+pre
701 759
702 760 # Completion logic:
703 761 # - user gives %%: only do cell magics
704 762 # - user gives %: do both line and cell magics
705 763 # - no prefix: do both
706 764 # In other words, line magics are skipped if the user gives %% explicitly
707 765 bare_text = text.lstrip(pre)
708 766 comp = [ pre2+m for m in cell_magics if m.startswith(bare_text)]
709 767 if not text.startswith(pre2):
710 768 comp += [ pre+m for m in line_magics if m.startswith(bare_text)]
711 769 return comp
712 770
713 771 def python_matches(self,text):
714 772 """Match attributes or global python names"""
715 773
716 774 #io.rprint('Completer->python_matches, txt=%r' % text) # dbg
717 775 if "." in text:
718 776 try:
719 777 matches = self.attr_matches(text)
720 778 if text.endswith('.') and self.omit__names:
721 779 if self.omit__names == 1:
722 780 # true if txt is _not_ a __ name, false otherwise:
723 781 no__name = (lambda txt:
724 782 re.match(r'.*\.__.*?__',txt) is None)
725 783 else:
726 784 # true if txt is _not_ a _ name, false otherwise:
727 785 no__name = (lambda txt:
728 786 re.match(r'\._.*?',txt[txt.rindex('.'):]) is None)
729 787 matches = filter(no__name, matches)
730 788 except NameError:
731 789 # catches <undefined attributes>.<tab>
732 790 matches = []
733 791 else:
734 792 matches = self.global_matches(text)
735 793
736 794 return matches
737 795
738 796 def _default_arguments_from_docstring(self, doc):
739 797 """Parse the first line of docstring for call signature.
740 798
741 799 Docstring should be of the form 'min(iterable[, key=func])\n'.
742 800 It can also parse cython docstring of the form
743 801 'Minuit.migrad(self, int ncall=10000, resume=True, int nsplit=1)'.
744 802 """
745 803 if doc is None:
746 804 return []
747 805
748 806 #care only the firstline
749 807 line = doc.lstrip().splitlines()[0]
750 808
751 809 #p = re.compile(r'^[\w|\s.]+\(([^)]*)\).*')
752 810 #'min(iterable[, key=func])\n' -> 'iterable[, key=func]'
753 811 sig = self.docstring_sig_re.search(line)
754 812 if sig is None:
755 813 return []
756 814 # iterable[, key=func]' -> ['iterable[' ,' key=func]']
757 815 sig = sig.groups()[0].split(',')
758 816 ret = []
759 817 for s in sig:
760 818 #re.compile(r'[\s|\[]*(\w+)(?:\s*=\s*.*)')
761 819 ret += self.docstring_kwd_re.findall(s)
762 820 return ret
763 821
764 822 def _default_arguments(self, obj):
765 823 """Return the list of default arguments of obj if it is callable,
766 824 or empty list otherwise."""
767 825 call_obj = obj
768 826 ret = []
769 827 if inspect.isbuiltin(obj):
770 828 pass
771 829 elif not (inspect.isfunction(obj) or inspect.ismethod(obj)):
772 830 if inspect.isclass(obj):
773 831 #for cython embededsignature=True the constructor docstring
774 832 #belongs to the object itself not __init__
775 833 ret += self._default_arguments_from_docstring(
776 834 getattr(obj, '__doc__', ''))
777 835 # for classes, check for __init__,__new__
778 836 call_obj = (getattr(obj, '__init__', None) or
779 837 getattr(obj, '__new__', None))
780 838 # for all others, check if they are __call__able
781 839 elif hasattr(obj, '__call__'):
782 840 call_obj = obj.__call__
783 841
784 842 ret += self._default_arguments_from_docstring(
785 843 getattr(call_obj, '__doc__', ''))
786 844
787 845 try:
788 846 args,_,_1,defaults = inspect.getargspec(call_obj)
789 847 if defaults:
790 848 ret+=args[-len(defaults):]
791 849 except TypeError:
792 850 pass
793 851
794 852 return list(set(ret))
795 853
796 854 def python_func_kw_matches(self,text):
797 855 """Match named parameters (kwargs) of the last open function"""
798 856
799 857 if "." in text: # a parameter cannot be dotted
800 858 return []
801 859 try: regexp = self.__funcParamsRegex
802 860 except AttributeError:
803 861 regexp = self.__funcParamsRegex = re.compile(r'''
804 862 '.*?(?<!\\)' | # single quoted strings or
805 863 ".*?(?<!\\)" | # double quoted strings or
806 864 \w+ | # identifier
807 865 \S # other characters
808 866 ''', re.VERBOSE | re.DOTALL)
809 867 # 1. find the nearest identifier that comes before an unclosed
810 868 # parenthesis before the cursor
811 869 # e.g. for "foo (1+bar(x), pa<cursor>,a=1)", the candidate is "foo"
812 870 tokens = regexp.findall(self.text_until_cursor)
813 871 tokens.reverse()
814 872 iterTokens = iter(tokens); openPar = 0
815 873
816 874 for token in iterTokens:
817 875 if token == ')':
818 876 openPar -= 1
819 877 elif token == '(':
820 878 openPar += 1
821 879 if openPar > 0:
822 880 # found the last unclosed parenthesis
823 881 break
824 882 else:
825 883 return []
826 884 # 2. Concatenate dotted names ("foo.bar" for "foo.bar(x, pa" )
827 885 ids = []
828 886 isId = re.compile(r'\w+$').match
829 887
830 888 while True:
831 889 try:
832 890 ids.append(next(iterTokens))
833 891 if not isId(ids[-1]):
834 892 ids.pop(); break
835 893 if not next(iterTokens) == '.':
836 894 break
837 895 except StopIteration:
838 896 break
839 897 # lookup the candidate callable matches either using global_matches
840 898 # or attr_matches for dotted names
841 899 if len(ids) == 1:
842 900 callableMatches = self.global_matches(ids[0])
843 901 else:
844 902 callableMatches = self.attr_matches('.'.join(ids[::-1]))
845 903 argMatches = []
846 904 for callableMatch in callableMatches:
847 905 try:
848 906 namedArgs = self._default_arguments(eval(callableMatch,
849 907 self.namespace))
850 908 except:
851 909 continue
852 910
853 911 for namedArg in namedArgs:
854 912 if namedArg.startswith(text):
855 913 argMatches.append("%s=" %namedArg)
856 914 return argMatches
857 915
858 916 def dict_key_matches(self, text):
859 917 "Match string keys in a dictionary, after e.g. 'foo[' "
860 918 def get_keys(obj):
861 919 # Only allow completion for known in-memory dict-like types
862 920 if isinstance(obj, dict) or\
863 921 _safe_isinstance(obj, 'pandas', 'DataFrame'):
864 922 try:
865 923 return list(obj.keys())
866 924 except Exception:
867 925 return []
868 926 elif _safe_isinstance(obj, 'numpy', 'ndarray') or\
869 927 _safe_isinstance(obj, 'numpy', 'void'):
870 928 return obj.dtype.names or []
871 929 return []
872 930
873 931 try:
874 932 regexps = self.__dict_key_regexps
875 933 except AttributeError:
876 934 dict_key_re_fmt = r'''(?x)
877 935 ( # match dict-referring expression wrt greedy setting
878 936 %s
879 937 )
880 938 \[ # open bracket
881 939 \s* # and optional whitespace
882 940 ([uUbB]? # string prefix (r not handled)
883 941 (?: # unclosed string
884 942 '(?:[^']|(?<!\\)\\')*
885 943 |
886 944 "(?:[^"]|(?<!\\)\\")*
887 945 )
888 946 )?
889 947 $
890 948 '''
891 949 regexps = self.__dict_key_regexps = {
892 950 False: re.compile(dict_key_re_fmt % '''
893 951 # identifiers separated by .
894 952 (?!\d)\w+
895 953 (?:\.(?!\d)\w+)*
896 954 '''),
897 955 True: re.compile(dict_key_re_fmt % '''
898 956 .+
899 957 ''')
900 958 }
901 959
902 960 match = regexps[self.greedy].search(self.text_until_cursor)
903 961 if match is None:
904 962 return []
905 963
906 964 expr, prefix = match.groups()
907 965 try:
908 966 obj = eval(expr, self.namespace)
909 967 except Exception:
910 968 try:
911 969 obj = eval(expr, self.global_namespace)
912 970 except Exception:
913 971 return []
914 972
915 973 keys = get_keys(obj)
916 974 if not keys:
917 975 return keys
918 976 closing_quote, token_offset, matches = match_dict_keys(keys, prefix)
919 977 if not matches:
920 978 return matches
921 979
922 980 # get the cursor position of
923 981 # - the text being completed
924 982 # - the start of the key text
925 983 # - the start of the completion
926 984 text_start = len(self.text_until_cursor) - len(text)
927 985 if prefix:
928 986 key_start = match.start(2)
929 987 completion_start = key_start + token_offset
930 988 else:
931 989 key_start = completion_start = match.end()
932 990
933 991 # grab the leading prefix, to make sure all completions start with `text`
934 992 if text_start > key_start:
935 993 leading = ''
936 994 else:
937 995 leading = text[text_start:completion_start]
938 996
939 997 # the index of the `[` character
940 998 bracket_idx = match.end(1)
941 999
942 1000 # append closing quote and bracket as appropriate
943 1001 # this is *not* appropriate if the opening quote or bracket is outside
944 1002 # the text given to this method
945 1003 suf = ''
946 1004 continuation = self.line_buffer[len(self.text_until_cursor):]
947 1005 if key_start > text_start and closing_quote:
948 1006 # quotes were opened inside text, maybe close them
949 1007 if continuation.startswith(closing_quote):
950 1008 continuation = continuation[len(closing_quote):]
951 1009 else:
952 1010 suf += closing_quote
953 1011 if bracket_idx > text_start:
954 1012 # brackets were opened inside text, maybe close them
955 1013 if not continuation.startswith(']'):
956 1014 suf += ']'
957 1015
958 1016 return [leading + k + suf for k in matches]
959 1017
960 1018 def unicode_name_matches(self, text):
961 1019 u"""Match Latex-like syntax for unicode characters base
962 1020 on the name of the character.
963 1021
964 1022 This does \\GREEK SMALL LETTER ETA -> Ξ·
965 1023
966 1024 Works only on valid python 3 identifier, or on combining characters that
967 1025 will combine to form a valid identifier.
968 1026
969 1027 Used on Python 3 only.
970 1028 """
971 1029 slashpos = text.rfind('\\')
972 1030 if slashpos > -1:
973 1031 s = text[slashpos+1:]
974 1032 try :
975 1033 unic = unicodedata.lookup(s)
976 1034 # allow combining chars
977 1035 if ('a'+unic).isidentifier():
978 1036 return '\\'+s,[unic]
979 1037 except KeyError as e:
980 1038 pass
981 1039 return u'', []
982 1040
983 def back_unicode_name_matches(self, text):
984 u"""Match unicode characters back to unicode name
985
986 This does β˜ƒ -> \\snowman
987
988 Note that snowman is not a valid python3 combining character but will be expanded.
989 Though it will not recombine back to the snowman character by the completion machinery.
990
991 This will not either back-complete standard sequences like \n, \b ...
992
993 Used on Python 3 only.
994 """
995 if len(text)<2:
996 return u'', ()
997 maybe_slash = text[-2]
998 if maybe_slash != '\\':
999 return u'', ()
1000
1001 char = text[-1]
1002 # no expand on quote for completion in strings.
1003 # nor backcomplete standard ascii keys
1004 if char in string.ascii_letters or char in ['"',"'"]:
1005 return u'', ()
1006 try :
1007 unic = unicodedata.name(char)
1008 return '\\'+char,['\\'+unic]
1009 except KeyError as e:
1010 pass
1011 return u'', ()
1012
1013 def back_latex_name_matches(self, text):
1014 u"""Match latex characters back to unicode name
1015
1016 This does ->\\sqrt
1017
1018 Used on Python 3 only.
1019 """
1020 if len(text)<2:
1021 return u'', ()
1022 maybe_slash = text[-2]
1023 if maybe_slash != '\\':
1024 return u'', ()
1025
1026
1027 char = text[-1]
1028 # no expand on quote for completion in strings.
1029 # nor backcomplete standard ascii keys
1030 if char in string.ascii_letters or char in ['"',"'"]:
1031 return u'', ()
1032 try :
1033 latex = reverse_latex_symbol[char]
1034 # '\\' replace the \ as well
1035 return '\\'+char,[latex]
1036 except KeyError as e:
1037 pass
1038 return u'', ()
1039 1041
1040 1042
1041 1043
1042 1044 def latex_matches(self, text):
1043 1045 u"""Match Latex syntax for unicode characters.
1044 1046
1045 1047 This does both \\alp -> \\alpha and \\alpha -> Ξ±
1046 1048
1047 1049 Used on Python 3 only.
1048 1050 """
1049 1051 slashpos = text.rfind('\\')
1050 1052 if slashpos > -1:
1051 1053 s = text[slashpos:]
1052 1054 if s in latex_symbols:
1053 1055 # Try to complete a full latex symbol to unicode
1054 1056 # \\alpha -> Ξ±
1055 1057 return s, [latex_symbols[s]]
1056 1058 else:
1057 1059 # If a user has partially typed a latex symbol, give them
1058 1060 # a full list of options \al -> [\aleph, \alpha]
1059 1061 matches = [k for k in latex_symbols if k.startswith(s)]
1060 1062 return s, matches
1061 1063 return u'', []
1062 1064
1063 1065 def dispatch_custom_completer(self, text):
1064 1066 #io.rprint("Custom! '%s' %s" % (text, self.custom_completers)) # dbg
1065 1067 line = self.line_buffer
1066 1068 if not line.strip():
1067 1069 return None
1068 1070
1069 1071 # Create a little structure to pass all the relevant information about
1070 1072 # the current completion to any custom completer.
1071 1073 event = Bunch()
1072 1074 event.line = line
1073 1075 event.symbol = text
1074 1076 cmd = line.split(None,1)[0]
1075 1077 event.command = cmd
1076 1078 event.text_until_cursor = self.text_until_cursor
1077 1079
1078 1080 #print "\ncustom:{%s]\n" % event # dbg
1079 1081
1080 1082 # for foo etc, try also to find completer for %foo
1081 1083 if not cmd.startswith(self.magic_escape):
1082 1084 try_magic = self.custom_completers.s_matches(
1083 1085 self.magic_escape + cmd)
1084 1086 else:
1085 1087 try_magic = []
1086 1088
1087 1089 for c in itertools.chain(self.custom_completers.s_matches(cmd),
1088 1090 try_magic,
1089 1091 self.custom_completers.flat_matches(self.text_until_cursor)):
1090 1092 #print "try",c # dbg
1091 1093 try:
1092 1094 res = c(event)
1093 1095 if res:
1094 1096 # first, try case sensitive match
1095 1097 withcase = [r for r in res if r.startswith(text)]
1096 1098 if withcase:
1097 1099 return withcase
1098 1100 # if none, then case insensitive ones are ok too
1099 1101 text_low = text.lower()
1100 1102 return [r for r in res if r.lower().startswith(text_low)]
1101 1103 except TryNext:
1102 1104 pass
1103 1105
1104 1106 return None
1105 1107
1106 1108 def complete(self, text=None, line_buffer=None, cursor_pos=None):
1107 1109 """Find completions for the given text and line context.
1108 1110
1109 1111 Note that both the text and the line_buffer are optional, but at least
1110 1112 one of them must be given.
1111 1113
1112 1114 Parameters
1113 1115 ----------
1114 1116 text : string, optional
1115 1117 Text to perform the completion on. If not given, the line buffer
1116 1118 is split using the instance's CompletionSplitter object.
1117 1119
1118 1120 line_buffer : string, optional
1119 1121 If not given, the completer attempts to obtain the current line
1120 1122 buffer via readline. This keyword allows clients which are
1121 1123 requesting for text completions in non-readline contexts to inform
1122 1124 the completer of the entire text.
1123 1125
1124 1126 cursor_pos : int, optional
1125 1127 Index of the cursor in the full line buffer. Should be provided by
1126 1128 remote frontends where kernel has no access to frontend state.
1127 1129
1128 1130 Returns
1129 1131 -------
1130 1132 text : str
1131 1133 Text that was actually used in the completion.
1132 1134
1133 1135 matches : list
1134 1136 A list of completion matches.
1135 1137 """
1136 1138 # io.rprint('\nCOMP1 %r %r %r' % (text, line_buffer, cursor_pos)) # dbg
1137 1139
1138 1140 # if the cursor position isn't given, the only sane assumption we can
1139 1141 # make is that it's at the end of the line (the common case)
1140 1142 if cursor_pos is None:
1141 1143 cursor_pos = len(line_buffer) if text is None else len(text)
1142 1144
1143 1145 if PY3:
1144 1146
1145 1147 base_text = text if not line_buffer else line_buffer[:cursor_pos]
1146 1148 latex_text, latex_matches = self.latex_matches(base_text)
1147 1149 if latex_matches:
1148 1150 return latex_text, latex_matches
1149 1151 name_text = ''
1150 1152 name_matches = []
1151 for meth in (self.unicode_name_matches, self.back_unicode_name_matches, self.back_latex_name_matches):
1152 _name_text, _name_matches = meth(base_text)
1153 if _name_text:
1154 name_text = _name_text
1155 name_matches.extend(_name_matches)
1156 if name_text:
1157 return name_text, name_matches
1153 for meth in (self.unicode_name_matches, back_latex_name_matches, back_unicode_name_matches):
1154 name_text, name_matches = meth(base_text)
1155 if name_text:
1156 return name_text, name_matches
1158 1157
1159 1158 # if text is either None or an empty string, rely on the line buffer
1160 1159 if not text:
1161 1160 text = self.splitter.split_line(line_buffer, cursor_pos)
1162 1161
1163 1162 # If no line buffer is given, assume the input text is all there was
1164 1163 if line_buffer is None:
1165 1164 line_buffer = text
1166 1165
1167 1166 self.line_buffer = line_buffer
1168 1167 self.text_until_cursor = self.line_buffer[:cursor_pos]
1169 1168 # io.rprint('COMP2 %r %r %r' % (text, line_buffer, cursor_pos)) # dbg
1170 1169
1171 1170 # Start with a clean slate of completions
1172 1171 self.matches[:] = []
1173 1172 custom_res = self.dispatch_custom_completer(text)
1174 1173 if custom_res is not None:
1175 1174 # did custom completers produce something?
1176 1175 self.matches = custom_res
1177 1176 else:
1178 1177 # Extend the list of completions with the results of each
1179 1178 # matcher, so we return results to the user from all
1180 1179 # namespaces.
1181 1180 if self.merge_completions:
1182 1181 self.matches = []
1183 1182 for matcher in self.matchers:
1184 1183 try:
1185 1184 self.matches.extend(matcher(text))
1186 1185 except:
1187 1186 # Show the ugly traceback if the matcher causes an
1188 1187 # exception, but do NOT crash the kernel!
1189 1188 sys.excepthook(*sys.exc_info())
1190 1189 else:
1191 1190 for matcher in self.matchers:
1192 1191 self.matches = matcher(text)
1193 1192 if self.matches:
1194 1193 break
1195 1194 # FIXME: we should extend our api to return a dict with completions for
1196 1195 # different types of objects. The rlcomplete() method could then
1197 1196 # simply collapse the dict into a list for readline, but we'd have
1198 1197 # richer completion semantics in other evironments.
1199 1198
1200 1199 # use penalize_magics_key to put magics after variables with same name
1201 1200 self.matches = sorted(set(self.matches), key=penalize_magics_key)
1202 1201
1203 1202 #io.rprint('COMP TEXT, MATCHES: %r, %r' % (text, self.matches)) # dbg
1204 1203 return text, self.matches
1205 1204
1206 1205 def rlcomplete(self, text, state):
1207 1206 """Return the state-th possible completion for 'text'.
1208 1207
1209 1208 This is called successively with state == 0, 1, 2, ... until it
1210 1209 returns None. The completion should begin with 'text'.
1211 1210
1212 1211 Parameters
1213 1212 ----------
1214 1213 text : string
1215 1214 Text to perform the completion on.
1216 1215
1217 1216 state : int
1218 1217 Counter used by readline.
1219 1218 """
1220 1219 if state==0:
1221 1220
1222 1221 self.line_buffer = line_buffer = self.readline.get_line_buffer()
1223 1222 cursor_pos = self.readline.get_endidx()
1224 1223
1225 1224 #io.rprint("\nRLCOMPLETE: %r %r %r" %
1226 1225 # (text, line_buffer, cursor_pos) ) # dbg
1227 1226
1228 1227 # if there is only a tab on a line with only whitespace, instead of
1229 1228 # the mostly useless 'do you want to see all million completions'
1230 1229 # message, just do the right thing and give the user his tab!
1231 1230 # Incidentally, this enables pasting of tabbed text from an editor
1232 1231 # (as long as autoindent is off).
1233 1232
1234 1233 # It should be noted that at least pyreadline still shows file
1235 1234 # completions - is there a way around it?
1236 1235
1237 1236 # don't apply this on 'dumb' terminals, such as emacs buffers, so
1238 1237 # we don't interfere with their own tab-completion mechanism.
1239 1238 if not (self.dumb_terminal or line_buffer.strip()):
1240 1239 self.readline.insert_text('\t')
1241 1240 sys.stdout.flush()
1242 1241 return None
1243 1242
1244 1243 # Note: debugging exceptions that may occur in completion is very
1245 1244 # tricky, because readline unconditionally silences them. So if
1246 1245 # during development you suspect a bug in the completion code, turn
1247 1246 # this flag on temporarily by uncommenting the second form (don't
1248 1247 # flip the value in the first line, as the '# dbg' marker can be
1249 1248 # automatically detected and is used elsewhere).
1250 1249 DEBUG = False
1251 1250 #DEBUG = True # dbg
1252 1251 if DEBUG:
1253 1252 try:
1254 1253 self.complete(text, line_buffer, cursor_pos)
1255 1254 except:
1256 1255 import traceback; traceback.print_exc()
1257 1256 else:
1258 1257 # The normal production version is here
1259 1258
1260 1259 # This method computes the self.matches array
1261 1260 self.complete(text, line_buffer, cursor_pos)
1262 1261
1263 1262 try:
1264 1263 return self.matches[state]
1265 1264 except IndexError:
1266 1265 return None
1267 1266
@@ -1,715 +1,754 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 IPython.config.loader import Config
16 16 from IPython.core import completer
17 17 from IPython.external.decorators import knownfailureif
18 18 from IPython.utils.tempdir import TemporaryDirectory, TemporaryWorkingDirectory
19 19 from IPython.utils.generics import complete_object
20 20 from IPython.utils import py3compat
21 21 from IPython.utils.py3compat import string_types, unicode_type
22 22 from IPython.testing import decorators as dec
23 23
24 24 #-----------------------------------------------------------------------------
25 25 # Test functions
26 26 #-----------------------------------------------------------------------------
27 27
28 28 @contextmanager
29 29 def greedy_completion():
30 30 ip = get_ipython()
31 31 greedy_original = ip.Completer.greedy
32 32 try:
33 33 ip.Completer.greedy = True
34 34 yield
35 35 finally:
36 36 ip.Completer.greedy = greedy_original
37 37
38 38 def test_protect_filename():
39 39 pairs = [ ('abc','abc'),
40 40 (' abc',r'\ abc'),
41 41 ('a bc',r'a\ bc'),
42 42 ('a bc',r'a\ \ bc'),
43 43 (' bc',r'\ \ bc'),
44 44 ]
45 45 # On posix, we also protect parens and other special characters
46 46 if sys.platform != 'win32':
47 47 pairs.extend( [('a(bc',r'a\(bc'),
48 48 ('a)bc',r'a\)bc'),
49 49 ('a( )bc',r'a\(\ \)bc'),
50 50 ('a[1]bc', r'a\[1\]bc'),
51 51 ('a{1}bc', r'a\{1\}bc'),
52 52 ('a#bc', r'a\#bc'),
53 53 ('a?bc', r'a\?bc'),
54 54 ('a=bc', r'a\=bc'),
55 55 ('a\\bc', r'a\\bc'),
56 56 ('a|bc', r'a\|bc'),
57 57 ('a;bc', r'a\;bc'),
58 58 ('a:bc', r'a\:bc'),
59 59 ("a'bc", r"a\'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 ] )
65 65 # run the actual tests
66 66 for s1, s2 in pairs:
67 67 s1p = completer.protect_filename(s1)
68 68 nt.assert_equal(s1p, s2)
69 69
70 70
71 71 def check_line_split(splitter, test_specs):
72 72 for part1, part2, split in test_specs:
73 73 cursor_pos = len(part1)
74 74 line = part1+part2
75 75 out = splitter.split_line(line, cursor_pos)
76 76 nt.assert_equal(out, split)
77 77
78 78
79 79 def test_line_split():
80 80 """Basic line splitter test with default specs."""
81 81 sp = completer.CompletionSplitter()
82 82 # The format of the test specs is: part1, part2, expected answer. Parts 1
83 83 # and 2 are joined into the 'line' sent to the splitter, as if the cursor
84 84 # was at the end of part1. So an empty part2 represents someone hitting
85 85 # tab at the end of the line, the most common case.
86 86 t = [('run some/scrip', '', 'some/scrip'),
87 87 ('run scripts/er', 'ror.py foo', 'scripts/er'),
88 88 ('echo $HOM', '', 'HOM'),
89 89 ('print sys.pa', '', 'sys.pa'),
90 90 ('print(sys.pa', '', 'sys.pa'),
91 91 ("execfile('scripts/er", '', 'scripts/er'),
92 92 ('a[x.', '', 'x.'),
93 93 ('a[x.', 'y', 'x.'),
94 94 ('cd "some_file/', '', 'some_file/'),
95 95 ]
96 96 check_line_split(sp, t)
97 97 # Ensure splitting works OK with unicode by re-running the tests with
98 98 # all inputs turned into unicode
99 99 check_line_split(sp, [ map(unicode_type, p) for p in t] )
100 100
101 101
102 102 def test_custom_completion_error():
103 103 """Test that errors from custom attribute completers are silenced."""
104 104 ip = get_ipython()
105 105 class A(object): pass
106 106 ip.user_ns['a'] = A()
107 107
108 108 @complete_object.when_type(A)
109 109 def complete_A(a, existing_completions):
110 110 raise TypeError("this should be silenced")
111 111
112 112 ip.complete("a.")
113 113
114 114
115 115 def test_unicode_completions():
116 116 ip = get_ipython()
117 117 # Some strings that trigger different types of completion. Check them both
118 118 # in str and unicode forms
119 119 s = ['ru', '%ru', 'cd /', 'floa', 'float(x)/']
120 120 for t in s + list(map(unicode_type, s)):
121 121 # We don't need to check exact completion values (they may change
122 122 # depending on the state of the namespace, but at least no exceptions
123 123 # should be thrown and the return value should be a pair of text, list
124 124 # values.
125 125 text, matches = ip.complete(t)
126 126 nt.assert_true(isinstance(text, string_types))
127 127 nt.assert_true(isinstance(matches, list))
128 128
129 129 @dec.onlyif(sys.version_info[0] >= 3, 'This test only applies in Py>=3')
130 130 def test_latex_completions():
131 131 from IPython.core.latex_symbols import latex_symbols
132 132 import random
133 133 ip = get_ipython()
134 134 # Test some random unicode symbols
135 135 keys = random.sample(latex_symbols.keys(), 10)
136 136 for k in keys:
137 137 text, matches = ip.complete(k)
138 138 nt.assert_equal(len(matches),1)
139 139 nt.assert_equal(text, k)
140 140 nt.assert_equal(matches[0], latex_symbols[k])
141 141 # Test a more complex line
142 142 text, matches = ip.complete(u'print(\\alpha')
143 143 nt.assert_equals(text, u'\\alpha')
144 144 nt.assert_equals(matches[0], latex_symbols['\\alpha'])
145 145 # Test multiple matching latex symbols
146 146 text, matches = ip.complete(u'\\al')
147 147 nt.assert_in('\\alpha', matches)
148 148 nt.assert_in('\\aleph', matches)
149 149
150 150
151
152
153 @dec.onlyif(sys.version_info[0] >= 3, 'This test only apply on python3')
154 def test_back_latex_completion():
155 ip = get_ipython()
156
157 # do not return more than 1 matches fro \beta, only the latex one.
158 name, matches = ip.complete('\\Ξ²')
159 nt.assert_equal(len(matches), 1)
160 nt.assert_equal(matches[0], '\\beta')
161
162 @dec.onlyif(sys.version_info[0] >= 3, 'This test only apply on python3')
163 def test_back_unicode_completion():
164 ip = get_ipython()
165
166 name, matches = ip.complete('\\β…€')
167 nt.assert_equal(len(matches), 1)
168 nt.assert_equal(matches[0], '\\ROMAN NUMERAL FIVE')
169
170
171 @dec.onlyif(sys.version_info[0] >= 3, 'This test only apply on python3')
172 def test_forward_unicode_completion():
173 ip = get_ipython()
174
175 name, matches = ip.complete('\\ROMAN NUMERAL FIVE')
176 nt.assert_equal(len(matches), 1)
177 nt.assert_equal(matches[0], 'β…€')
178
179 @dec.onlyif(sys.version_info[0] >= 3, 'This test only apply on python3')
180 def test_no_ascii_back_completion():
181 ip = get_ipython()
182 # single ascii letter that don't have yet completions
183 for letter in 'fjqyJMQVWY' :
184 name, matches = ip.complete('\\'+letter)
185 nt.assert_equal(len(matches), 0)
186
187
188
189
151 190 class CompletionSplitterTestCase(unittest.TestCase):
152 191 def setUp(self):
153 192 self.sp = completer.CompletionSplitter()
154 193
155 194 def test_delim_setting(self):
156 195 self.sp.delims = ' '
157 196 nt.assert_equal(self.sp.delims, ' ')
158 197 nt.assert_equal(self.sp._delim_expr, '[\ ]')
159 198
160 199 def test_spaces(self):
161 200 """Test with only spaces as split chars."""
162 201 self.sp.delims = ' '
163 202 t = [('foo', '', 'foo'),
164 203 ('run foo', '', 'foo'),
165 204 ('run foo', 'bar', 'foo'),
166 205 ]
167 206 check_line_split(self.sp, t)
168 207
169 208
170 209 def test_has_open_quotes1():
171 210 for s in ["'", "'''", "'hi' '"]:
172 211 nt.assert_equal(completer.has_open_quotes(s), "'")
173 212
174 213
175 214 def test_has_open_quotes2():
176 215 for s in ['"', '"""', '"hi" "']:
177 216 nt.assert_equal(completer.has_open_quotes(s), '"')
178 217
179 218
180 219 def test_has_open_quotes3():
181 220 for s in ["''", "''' '''", "'hi' 'ipython'"]:
182 221 nt.assert_false(completer.has_open_quotes(s))
183 222
184 223
185 224 def test_has_open_quotes4():
186 225 for s in ['""', '""" """', '"hi" "ipython"']:
187 226 nt.assert_false(completer.has_open_quotes(s))
188 227
189 228
190 229 @knownfailureif(sys.platform == 'win32', "abspath completions fail on Windows")
191 230 def test_abspath_file_completions():
192 231 ip = get_ipython()
193 232 with TemporaryDirectory() as tmpdir:
194 233 prefix = os.path.join(tmpdir, 'foo')
195 234 suffixes = ['1', '2']
196 235 names = [prefix+s for s in suffixes]
197 236 for n in names:
198 237 open(n, 'w').close()
199 238
200 239 # Check simple completion
201 240 c = ip.complete(prefix)[1]
202 241 nt.assert_equal(c, names)
203 242
204 243 # Now check with a function call
205 244 cmd = 'a = f("%s' % prefix
206 245 c = ip.complete(prefix, cmd)[1]
207 246 comp = [prefix+s for s in suffixes]
208 247 nt.assert_equal(c, comp)
209 248
210 249
211 250 def test_local_file_completions():
212 251 ip = get_ipython()
213 252 with TemporaryWorkingDirectory():
214 253 prefix = './foo'
215 254 suffixes = ['1', '2']
216 255 names = [prefix+s for s in suffixes]
217 256 for n in names:
218 257 open(n, 'w').close()
219 258
220 259 # Check simple completion
221 260 c = ip.complete(prefix)[1]
222 261 nt.assert_equal(c, names)
223 262
224 263 # Now check with a function call
225 264 cmd = 'a = f("%s' % prefix
226 265 c = ip.complete(prefix, cmd)[1]
227 266 comp = [prefix+s for s in suffixes]
228 267 nt.assert_equal(c, comp)
229 268
230 269
231 270 def test_greedy_completions():
232 271 ip = get_ipython()
233 272 ip.ex('a=list(range(5))')
234 273 _,c = ip.complete('.',line='a[0].')
235 274 nt.assert_false('a[0].real' in c,
236 275 "Shouldn't have completed on a[0]: %s"%c)
237 276 with greedy_completion():
238 277 _,c = ip.complete('.',line='a[0].')
239 278 nt.assert_true('a[0].real' in c, "Should have completed on a[0]: %s"%c)
240 279
241 280
242 281 def test_omit__names():
243 282 # also happens to test IPCompleter as a configurable
244 283 ip = get_ipython()
245 284 ip._hidden_attr = 1
246 285 ip._x = {}
247 286 c = ip.Completer
248 287 ip.ex('ip=get_ipython()')
249 288 cfg = Config()
250 289 cfg.IPCompleter.omit__names = 0
251 290 c.update_config(cfg)
252 291 s,matches = c.complete('ip.')
253 292 nt.assert_in('ip.__str__', matches)
254 293 nt.assert_in('ip._hidden_attr', matches)
255 294 cfg.IPCompleter.omit__names = 1
256 295 c.update_config(cfg)
257 296 s,matches = c.complete('ip.')
258 297 nt.assert_not_in('ip.__str__', matches)
259 298 nt.assert_in('ip._hidden_attr', matches)
260 299 cfg.IPCompleter.omit__names = 2
261 300 c.update_config(cfg)
262 301 s,matches = c.complete('ip.')
263 302 nt.assert_not_in('ip.__str__', matches)
264 303 nt.assert_not_in('ip._hidden_attr', matches)
265 304 s,matches = c.complete('ip._x.')
266 305 nt.assert_in('ip._x.keys', matches)
267 306 del ip._hidden_attr
268 307
269 308
270 309 def test_limit_to__all__False_ok():
271 310 ip = get_ipython()
272 311 c = ip.Completer
273 312 ip.ex('class D: x=24')
274 313 ip.ex('d=D()')
275 314 cfg = Config()
276 315 cfg.IPCompleter.limit_to__all__ = False
277 316 c.update_config(cfg)
278 317 s, matches = c.complete('d.')
279 318 nt.assert_in('d.x', matches)
280 319
281 320
282 321 def test_limit_to__all__True_ok():
283 322 ip = get_ipython()
284 323 c = ip.Completer
285 324 ip.ex('class D: x=24')
286 325 ip.ex('d=D()')
287 326 ip.ex("d.__all__=['z']")
288 327 cfg = Config()
289 328 cfg.IPCompleter.limit_to__all__ = True
290 329 c.update_config(cfg)
291 330 s, matches = c.complete('d.')
292 331 nt.assert_in('d.z', matches)
293 332 nt.assert_not_in('d.x', matches)
294 333
295 334
296 335 def test_get__all__entries_ok():
297 336 class A(object):
298 337 __all__ = ['x', 1]
299 338 words = completer.get__all__entries(A())
300 339 nt.assert_equal(words, ['x'])
301 340
302 341
303 342 def test_get__all__entries_no__all__ok():
304 343 class A(object):
305 344 pass
306 345 words = completer.get__all__entries(A())
307 346 nt.assert_equal(words, [])
308 347
309 348
310 349 def test_func_kw_completions():
311 350 ip = get_ipython()
312 351 c = ip.Completer
313 352 ip.ex('def myfunc(a=1,b=2): return a+b')
314 353 s, matches = c.complete(None, 'myfunc(1,b')
315 354 nt.assert_in('b=', matches)
316 355 # Simulate completing with cursor right after b (pos==10):
317 356 s, matches = c.complete(None, 'myfunc(1,b)', 10)
318 357 nt.assert_in('b=', matches)
319 358 s, matches = c.complete(None, 'myfunc(a="escaped\\")string",b')
320 359 nt.assert_in('b=', matches)
321 360 #builtin function
322 361 s, matches = c.complete(None, 'min(k, k')
323 362 nt.assert_in('key=', matches)
324 363
325 364
326 365 def test_default_arguments_from_docstring():
327 366 doc = min.__doc__
328 367 ip = get_ipython()
329 368 c = ip.Completer
330 369 kwd = c._default_arguments_from_docstring(
331 370 'min(iterable[, key=func]) -> value')
332 371 nt.assert_equal(kwd, ['key'])
333 372 #with cython type etc
334 373 kwd = c._default_arguments_from_docstring(
335 374 'Minuit.migrad(self, int ncall=10000, resume=True, int nsplit=1)\n')
336 375 nt.assert_equal(kwd, ['ncall', 'resume', 'nsplit'])
337 376 #white spaces
338 377 kwd = c._default_arguments_from_docstring(
339 378 '\n Minuit.migrad(self, int ncall=10000, resume=True, int nsplit=1)\n')
340 379 nt.assert_equal(kwd, ['ncall', 'resume', 'nsplit'])
341 380
342 381 def test_line_magics():
343 382 ip = get_ipython()
344 383 c = ip.Completer
345 384 s, matches = c.complete(None, 'lsmag')
346 385 nt.assert_in('%lsmagic', matches)
347 386 s, matches = c.complete(None, '%lsmag')
348 387 nt.assert_in('%lsmagic', matches)
349 388
350 389
351 390 def test_cell_magics():
352 391 from IPython.core.magic import register_cell_magic
353 392
354 393 @register_cell_magic
355 394 def _foo_cellm(line, cell):
356 395 pass
357 396
358 397 ip = get_ipython()
359 398 c = ip.Completer
360 399
361 400 s, matches = c.complete(None, '_foo_ce')
362 401 nt.assert_in('%%_foo_cellm', matches)
363 402 s, matches = c.complete(None, '%%_foo_ce')
364 403 nt.assert_in('%%_foo_cellm', matches)
365 404
366 405
367 406 def test_line_cell_magics():
368 407 from IPython.core.magic import register_line_cell_magic
369 408
370 409 @register_line_cell_magic
371 410 def _bar_cellm(line, cell):
372 411 pass
373 412
374 413 ip = get_ipython()
375 414 c = ip.Completer
376 415
377 416 # The policy here is trickier, see comments in completion code. The
378 417 # returned values depend on whether the user passes %% or not explicitly,
379 418 # and this will show a difference if the same name is both a line and cell
380 419 # magic.
381 420 s, matches = c.complete(None, '_bar_ce')
382 421 nt.assert_in('%_bar_cellm', matches)
383 422 nt.assert_in('%%_bar_cellm', matches)
384 423 s, matches = c.complete(None, '%_bar_ce')
385 424 nt.assert_in('%_bar_cellm', matches)
386 425 nt.assert_in('%%_bar_cellm', matches)
387 426 s, matches = c.complete(None, '%%_bar_ce')
388 427 nt.assert_not_in('%_bar_cellm', matches)
389 428 nt.assert_in('%%_bar_cellm', matches)
390 429
391 430
392 431 def test_magic_completion_order():
393 432
394 433 ip = get_ipython()
395 434 c = ip.Completer
396 435
397 436 # Test ordering of magics and non-magics with the same name
398 437 # We want the non-magic first
399 438
400 439 # Before importing matplotlib, there should only be one option:
401 440
402 441 text, matches = c.complete('mat')
403 442 nt.assert_equal(matches, ["%matplotlib"])
404 443
405 444
406 445 ip.run_cell("matplotlib = 1") # introduce name into namespace
407 446
408 447 # After the import, there should be two options, ordered like this:
409 448 text, matches = c.complete('mat')
410 449 nt.assert_equal(matches, ["matplotlib", "%matplotlib"])
411 450
412 451
413 452 ip.run_cell("timeit = 1") # define a user variable called 'timeit'
414 453
415 454 # Order of user variable and line and cell magics with same name:
416 455 text, matches = c.complete('timeit')
417 456 nt.assert_equal(matches, ["timeit", "%timeit","%%timeit"])
418 457
419 458
420 459 def test_dict_key_completion_string():
421 460 """Test dictionary key completion for string keys"""
422 461 ip = get_ipython()
423 462 complete = ip.Completer.complete
424 463
425 464 ip.user_ns['d'] = {'abc': None}
426 465
427 466 # check completion at different stages
428 467 _, matches = complete(line_buffer="d[")
429 468 nt.assert_in("'abc'", matches)
430 469 nt.assert_not_in("'abc']", matches)
431 470
432 471 _, matches = complete(line_buffer="d['")
433 472 nt.assert_in("abc", matches)
434 473 nt.assert_not_in("abc']", matches)
435 474
436 475 _, matches = complete(line_buffer="d['a")
437 476 nt.assert_in("abc", matches)
438 477 nt.assert_not_in("abc']", matches)
439 478
440 479 # check use of different quoting
441 480 _, matches = complete(line_buffer="d[\"")
442 481 nt.assert_in("abc", matches)
443 482 nt.assert_not_in('abc\"]', matches)
444 483
445 484 _, matches = complete(line_buffer="d[\"a")
446 485 nt.assert_in("abc", matches)
447 486 nt.assert_not_in('abc\"]', matches)
448 487
449 488 # check sensitivity to following context
450 489 _, matches = complete(line_buffer="d[]", cursor_pos=2)
451 490 nt.assert_in("'abc'", matches)
452 491
453 492 _, matches = complete(line_buffer="d['']", cursor_pos=3)
454 493 nt.assert_in("abc", matches)
455 494 nt.assert_not_in("abc'", matches)
456 495 nt.assert_not_in("abc']", matches)
457 496
458 497 # check multiple solutions are correctly returned and that noise is not
459 498 ip.user_ns['d'] = {'abc': None, 'abd': None, 'bad': None, object(): None,
460 499 5: None}
461 500
462 501 _, matches = complete(line_buffer="d['a")
463 502 nt.assert_in("abc", matches)
464 503 nt.assert_in("abd", matches)
465 504 nt.assert_not_in("bad", matches)
466 505 assert not any(m.endswith((']', '"', "'")) for m in matches), matches
467 506
468 507 # check escaping and whitespace
469 508 ip.user_ns['d'] = {'a\nb': None, 'a\'b': None, 'a"b': None, 'a word': None}
470 509 _, matches = complete(line_buffer="d['a")
471 510 nt.assert_in("a\\nb", matches)
472 511 nt.assert_in("a\\'b", matches)
473 512 nt.assert_in("a\"b", matches)
474 513 nt.assert_in("a word", matches)
475 514 assert not any(m.endswith((']', '"', "'")) for m in matches), matches
476 515
477 516 # - can complete on non-initial word of the string
478 517 _, matches = complete(line_buffer="d['a w")
479 518 nt.assert_in("word", matches)
480 519
481 520 # - understands quote escaping
482 521 _, matches = complete(line_buffer="d['a\\'")
483 522 nt.assert_in("b", matches)
484 523
485 524 # - default quoting should work like repr
486 525 _, matches = complete(line_buffer="d[")
487 526 nt.assert_in("\"a'b\"", matches)
488 527
489 528 # - when opening quote with ", possible to match with unescaped apostrophe
490 529 _, matches = complete(line_buffer="d[\"a'")
491 530 nt.assert_in("b", matches)
492 531
493 532
494 533 def test_dict_key_completion_contexts():
495 534 """Test expression contexts in which dict key completion occurs"""
496 535 ip = get_ipython()
497 536 complete = ip.Completer.complete
498 537 d = {'abc': None}
499 538 ip.user_ns['d'] = d
500 539
501 540 class C:
502 541 data = d
503 542 ip.user_ns['C'] = C
504 543 ip.user_ns['get'] = lambda: d
505 544
506 545 def assert_no_completion(**kwargs):
507 546 _, matches = complete(**kwargs)
508 547 nt.assert_not_in('abc', matches)
509 548 nt.assert_not_in('abc\'', matches)
510 549 nt.assert_not_in('abc\']', matches)
511 550 nt.assert_not_in('\'abc\'', matches)
512 551 nt.assert_not_in('\'abc\']', matches)
513 552
514 553 def assert_completion(**kwargs):
515 554 _, matches = complete(**kwargs)
516 555 nt.assert_in("'abc'", matches)
517 556 nt.assert_not_in("'abc']", matches)
518 557
519 558 # no completion after string closed, even if reopened
520 559 assert_no_completion(line_buffer="d['a'")
521 560 assert_no_completion(line_buffer="d[\"a\"")
522 561 assert_no_completion(line_buffer="d['a' + ")
523 562 assert_no_completion(line_buffer="d['a' + '")
524 563
525 564 # completion in non-trivial expressions
526 565 assert_completion(line_buffer="+ d[")
527 566 assert_completion(line_buffer="(d[")
528 567 assert_completion(line_buffer="C.data[")
529 568
530 569 # greedy flag
531 570 def assert_completion(**kwargs):
532 571 _, matches = complete(**kwargs)
533 572 nt.assert_in("get()['abc']", matches)
534 573
535 574 assert_no_completion(line_buffer="get()[")
536 575 with greedy_completion():
537 576 assert_completion(line_buffer="get()[")
538 577 assert_completion(line_buffer="get()['")
539 578 assert_completion(line_buffer="get()['a")
540 579 assert_completion(line_buffer="get()['ab")
541 580 assert_completion(line_buffer="get()['abc")
542 581
543 582
544 583
545 584 @dec.onlyif(sys.version_info[0] >= 3, 'This test only applies in Py>=3')
546 585 def test_dict_key_completion_bytes():
547 586 """Test handling of bytes in dict key completion"""
548 587 ip = get_ipython()
549 588 complete = ip.Completer.complete
550 589
551 590 ip.user_ns['d'] = {'abc': None, b'abd': None}
552 591
553 592 _, matches = complete(line_buffer="d[")
554 593 nt.assert_in("'abc'", matches)
555 594 nt.assert_in("b'abd'", matches)
556 595
557 596 if False: # not currently implemented
558 597 _, matches = complete(line_buffer="d[b")
559 598 nt.assert_in("b'abd'", matches)
560 599 nt.assert_not_in("b'abc'", matches)
561 600
562 601 _, matches = complete(line_buffer="d[b'")
563 602 nt.assert_in("abd", matches)
564 603 nt.assert_not_in("abc", matches)
565 604
566 605 _, matches = complete(line_buffer="d[B'")
567 606 nt.assert_in("abd", matches)
568 607 nt.assert_not_in("abc", matches)
569 608
570 609 _, matches = complete(line_buffer="d['")
571 610 nt.assert_in("abc", matches)
572 611 nt.assert_not_in("abd", matches)
573 612
574 613
575 614 @dec.onlyif(sys.version_info[0] < 3, 'This test only applies in Py<3')
576 615 def test_dict_key_completion_unicode_py2():
577 616 """Test handling of unicode in dict key completion"""
578 617 ip = get_ipython()
579 618 complete = ip.Completer.complete
580 619
581 620 ip.user_ns['d'] = {u'abc': None,
582 621 u'a\u05d0b': None}
583 622
584 623 _, matches = complete(line_buffer="d[")
585 624 nt.assert_in("u'abc'", matches)
586 625 nt.assert_in("u'a\\u05d0b'", matches)
587 626
588 627 _, matches = complete(line_buffer="d['a")
589 628 nt.assert_in("abc", matches)
590 629 nt.assert_not_in("a\\u05d0b", matches)
591 630
592 631 _, matches = complete(line_buffer="d[u'a")
593 632 nt.assert_in("abc", matches)
594 633 nt.assert_in("a\\u05d0b", matches)
595 634
596 635 _, matches = complete(line_buffer="d[U'a")
597 636 nt.assert_in("abc", matches)
598 637 nt.assert_in("a\\u05d0b", matches)
599 638
600 639 # query using escape
601 640 _, matches = complete(line_buffer=u"d[u'a\\u05d0")
602 641 nt.assert_in("u05d0b", matches) # tokenized after \\
603 642
604 643 # query using character
605 644 _, matches = complete(line_buffer=u"d[u'a\u05d0")
606 645 nt.assert_in(u"a\u05d0b", matches)
607 646
608 647 with greedy_completion():
609 648 _, matches = complete(line_buffer="d[")
610 649 nt.assert_in("d[u'abc']", matches)
611 650 nt.assert_in("d[u'a\\u05d0b']", matches)
612 651
613 652 _, matches = complete(line_buffer="d['a")
614 653 nt.assert_in("d['abc']", matches)
615 654 nt.assert_not_in("d[u'a\\u05d0b']", matches)
616 655
617 656 _, matches = complete(line_buffer="d[u'a")
618 657 nt.assert_in("d[u'abc']", matches)
619 658 nt.assert_in("d[u'a\\u05d0b']", matches)
620 659
621 660 _, matches = complete(line_buffer="d[U'a")
622 661 nt.assert_in("d[U'abc']", matches)
623 662 nt.assert_in("d[U'a\\u05d0b']", matches)
624 663
625 664 # query using escape
626 665 _, matches = complete(line_buffer=u"d[u'a\\u05d0")
627 666 nt.assert_in("d[u'a\\u05d0b']", matches) # tokenized after \\
628 667
629 668 # query using character
630 669 _, matches = complete(line_buffer=u"d[u'a\u05d0")
631 670 nt.assert_in(u"d[u'a\u05d0b']", matches)
632 671
633 672
634 673 @dec.onlyif(sys.version_info[0] >= 3, 'This test only applies in Py>=3')
635 674 def test_dict_key_completion_unicode_py3():
636 675 """Test handling of unicode in dict key completion"""
637 676 ip = get_ipython()
638 677 complete = ip.Completer.complete
639 678
640 679 ip.user_ns['d'] = {u'a\u05d0': None}
641 680
642 681 # query using escape
643 682 _, matches = complete(line_buffer="d['a\\u05d0")
644 683 nt.assert_in("u05d0", matches) # tokenized after \\
645 684
646 685 # query using character
647 686 _, matches = complete(line_buffer="d['a\u05d0")
648 687 nt.assert_in(u"a\u05d0", matches)
649 688
650 689 with greedy_completion():
651 690 # query using escape
652 691 _, matches = complete(line_buffer="d['a\\u05d0")
653 692 nt.assert_in("d['a\\u05d0']", matches) # tokenized after \\
654 693
655 694 # query using character
656 695 _, matches = complete(line_buffer="d['a\u05d0")
657 696 nt.assert_in(u"d['a\u05d0']", matches)
658 697
659 698
660 699
661 700 @dec.skip_without('numpy')
662 701 def test_struct_array_key_completion():
663 702 """Test dict key completion applies to numpy struct arrays"""
664 703 import numpy
665 704 ip = get_ipython()
666 705 complete = ip.Completer.complete
667 706 ip.user_ns['d'] = numpy.array([], dtype=[('hello', 'f'), ('world', 'f')])
668 707 _, matches = complete(line_buffer="d['")
669 708 nt.assert_in("hello", matches)
670 709 nt.assert_in("world", matches)
671 710 # complete on the numpy struct itself
672 711 dt = numpy.dtype([('my_head', [('my_dt', '>u4'), ('my_df', '>u4')]),
673 712 ('my_data', '>f4', 5)])
674 713 x = numpy.zeros(2, dtype=dt)
675 714 ip.user_ns['d'] = x[1]
676 715 _, matches = complete(line_buffer="d['")
677 716 nt.assert_in("my_head", matches)
678 717 nt.assert_in("my_data", matches)
679 718 # complete on a nested level
680 719 with greedy_completion():
681 720 ip.user_ns['d'] = numpy.zeros(2, dtype=dt)
682 721 _, matches = complete(line_buffer="d[1]['my_head']['")
683 722 nt.assert_true(any(["my_dt" in m for m in matches]))
684 723 nt.assert_true(any(["my_df" in m for m in matches]))
685 724
686 725
687 726 @dec.skip_without('pandas')
688 727 def test_dataframe_key_completion():
689 728 """Test dict key completion applies to pandas DataFrames"""
690 729 import pandas
691 730 ip = get_ipython()
692 731 complete = ip.Completer.complete
693 732 ip.user_ns['d'] = pandas.DataFrame({'hello': [1], 'world': [2]})
694 733 _, matches = complete(line_buffer="d['")
695 734 nt.assert_in("hello", matches)
696 735 nt.assert_in("world", matches)
697 736
698 737
699 738 def test_dict_key_completion_invalids():
700 739 """Smoke test cases dict key completion can't handle"""
701 740 ip = get_ipython()
702 741 complete = ip.Completer.complete
703 742
704 743 ip.user_ns['no_getitem'] = None
705 744 ip.user_ns['no_keys'] = []
706 745 ip.user_ns['cant_call_keys'] = dict
707 746 ip.user_ns['empty'] = {}
708 747 ip.user_ns['d'] = {'abc': 5}
709 748
710 749 _, matches = complete(line_buffer="no_getitem['")
711 750 _, matches = complete(line_buffer="no_keys['")
712 751 _, matches = complete(line_buffer="cant_call_keys['")
713 752 _, matches = complete(line_buffer="empty['")
714 753 _, matches = complete(line_buffer="name_error['")
715 754 _, matches = complete(line_buffer="d['\\") # incomplete escape
General Comments 0
You need to be logged in to leave comments. Login now