##// END OF EJS Templates
Merge pull request #9375 from liukelly/jedi_completion...
Matthias Bussonnier -
r22297:730393a7 merge
parent child Browse files
Show More
@@ -53,6 +53,8 b' Notes:'
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 from __future__ import print_function
57
56 58 import __main__
57 59 import glob
58 60 import inspect
@@ -75,6 +77,14 b' from IPython.utils.process import arg_split'
75 77 from IPython.utils.py3compat import builtin_mod, string_types, PY3, cast_unicode_py2
76 78 from traitlets import CBool, Enum
77 79
80 try:
81 import jedi
82 import jedi.api.helpers
83 import jedi.parser.user_context
84 JEDI_INSTALLED = True
85 except ImportError:
86 JEDI_INSTALLED = False
87
78 88 #-----------------------------------------------------------------------------
79 89 # Globals
80 90 #-----------------------------------------------------------------------------
@@ -269,6 +279,7 b' class Completer(Configurable):'
269 279
270 280 greedy = CBool(False, config=True,
271 281 help="""Activate greedy completion
282 PENDING DEPRECTION. this is now mostly taken care of with Jedi.
272 283
273 284 This will enable completion on elements of lists, results of function calls, etc.,
274 285 but can be unsafe because the code is actually evaluated on TAB.
@@ -279,7 +290,7 b' class Completer(Configurable):'
279 290 def __init__(self, namespace=None, global_namespace=None, **kwargs):
280 291 """Create a new completer for the command line.
281 292
282 Completer(namespace=ns,global_namespace=ns2) -> completer instance.
293 Completer(namespace=ns, global_namespace=ns2) -> completer instance.
283 294
284 295 If unspecified, the default namespace where completions are performed
285 296 is __main__ (technically, __main__.__dict__). Namespaces should be
@@ -339,7 +350,6 b' class Completer(Configurable):'
339 350 defined in self.namespace or self.global_namespace that match.
340 351
341 352 """
342 #print 'Completer->global_matches, txt=%r' % text # dbg
343 353 matches = []
344 354 match_append = matches.append
345 355 n = len(text)
@@ -366,7 +376,6 b' class Completer(Configurable):'
366 376
367 377 """
368 378
369 #io.rprint('Completer->attr_matches, txt=%r' % text) # dbg
370 379 # Another option, seems to work great. Catches things like ''.<tab>
371 380 m = re.match(r"(\S+(\.\w+)*)\.(\w*)$", text)
372 381
@@ -565,7 +574,10 b' class IPCompleter(Completer):'
565 574 """
566 575 )
567 576 limit_to__all__ = CBool(default_value=False, config=True,
568 help="""Instruct the completer to use __all__ for the completion
577 help="""
578 DEPRECATED as of version 5.0.
579
580 Instruct the completer to use __all__ for the completion
569 581
570 582 Specifically, when completing on ``object.<tab>``.
571 583
@@ -574,6 +586,9 b' class IPCompleter(Completer):'
574 586 When False [default]: the __all__ attribute is ignored
575 587 """
576 588 )
589 use_jedi_completions = CBool(default_value=JEDI_INSTALLED, config=True,
590 help="""Use Jedi to generate autocompletions.
591 """)
577 592
578 593 def __init__(self, shell=None, namespace=None, global_namespace=None,
579 594 use_readline=True, config=None, **kwargs):
@@ -640,7 +655,7 b' class IPCompleter(Completer):'
640 655 #= re.compile(r'[\s|\[]*(\w+)(?:\s*=?\s*.*)')
641 656
642 657 # All active matcher routines for completion
643 self.matchers = [self.python_matches,
658 self.matchers = [
644 659 self.file_matches,
645 660 self.magic_matches,
646 661 self.python_func_kw_matches,
@@ -654,7 +669,7 b' class IPCompleter(Completer):'
654 669 """
655 670 return self.complete(text)[1]
656 671
657 def _clean_glob(self,text):
672 def _clean_glob(self, text):
658 673 return self.glob("%s*" % text)
659 674
660 675 def _clean_glob_win32(self,text):
@@ -675,8 +690,6 b' class IPCompleter(Completer):'
675 690 current (as of Python 2.3) Python readline it's possible to do
676 691 better."""
677 692
678 #io.rprint('Completer->file_matches: <%r>' % text) # dbg
679
680 693 # chars that require escaping with backslash - i.e. chars
681 694 # that readline treats incorrectly as delimiters, but we
682 695 # don't want to treat as delimiters in filename matching
@@ -743,7 +756,6 b' class IPCompleter(Completer):'
743 756
744 757 def magic_matches(self, text):
745 758 """Match magics"""
746 #print 'Completer->magic_matches:',text,'lb',self.text_until_cursor # dbg
747 759 # Get all shell magics now rather than statically, so magics loaded at
748 760 # runtime show up too.
749 761 lsm = self.shell.magics_manager.lsmagic()
@@ -763,10 +775,62 b' class IPCompleter(Completer):'
763 775 comp += [ pre+m for m in line_magics if m.startswith(bare_text)]
764 776 return [cast_unicode_py2(c) for c in comp]
765 777
778 def python_jedi_matches(self, text, line_buffer, cursor_pos):
779 """Match attributes or global Python names using Jedi."""
780 if line_buffer.startswith('aimport ') or line_buffer.startswith('%aimport '):
781 return ()
782 namespaces = []
783 if self.namespace is None:
784 import __main__
785 namespaces.append(__main__.__dict__)
786 else:
787 namespaces.append(self.namespace)
788 if self.global_namespace is not None:
789 namespaces.append(self.global_namespace)
790
791 # cursor_pos is an it, jedi wants line and column
792
793 interpreter = jedi.Interpreter(line_buffer, namespaces, column=cursor_pos)
794 path = jedi.parser.user_context.UserContext(line_buffer, \
795 (1, len(line_buffer))).get_path_until_cursor()
796 path, dot, like = jedi.api.helpers.completion_parts(path)
797 if text.startswith('.'):
798 # text will be `.` on completions like `a[0].<tab>`
799 before = dot
800 else:
801 before = line_buffer[:len(line_buffer) - len(like)]
802
803
804 def trim_start(completion):
805 """completions need to start with `text`, trim the beginning until it does"""
806 if text in completion and not (completion.startswith(text)):
807 start_index = completion.index(text)
808 if cursor_pos:
809 assert start_index < cursor_pos
810 return completion[start_index:]
811 return completion
812
813 completions = interpreter.completions()
814
815 completion_text = [c.name_with_symbols for c in completions]
816
817 if self.omit__names:
818 if self.omit__names == 1:
819 # true if txt is _not_ a __ name, false otherwise:
820 no__name = lambda txt: not txt.startswith('__')
821 else:
822 # true if txt is _not_ a _ name, false otherwise:
823 no__name = lambda txt: not txt.startswith('_')
824 completion_text = filter(no__name, completion_text)
825
826
827 return [trim_start(before + c_text) for c_text in completion_text]
828
829
766 830 def python_matches(self, text):
767 831 """Match attributes or global python names"""
768
769 #io.rprint('Completer->python_matches, txt=%r' % text) # dbg
832 # Jedi completion
833
770 834 if "." in text:
771 835 try:
772 836 matches = self.attr_matches(text)
@@ -1085,8 +1149,6 b' class IPCompleter(Completer):'
1085 1149 event.command = cmd
1086 1150 event.text_until_cursor = self.text_until_cursor
1087 1151
1088 #print "\ncustom:{%s]\n" % event # dbg
1089
1090 1152 # for foo etc, try also to find completer for %foo
1091 1153 if not cmd.startswith(self.magic_escape):
1092 1154 try_magic = self.custom_completers.s_matches(
@@ -1142,8 +1204,6 b' class IPCompleter(Completer):'
1142 1204 matches : list
1143 1205 A list of completion matches.
1144 1206 """
1145 # io.rprint('\nCOMP1 %r %r %r' % (text, line_buffer, cursor_pos)) # dbg
1146
1147 1207 # if the cursor position isn't given, the only sane assumption we can
1148 1208 # make is that it's at the end of the line (the common case)
1149 1209 if cursor_pos is None:
@@ -1172,7 +1232,6 b' class IPCompleter(Completer):'
1172 1232
1173 1233 self.line_buffer = line_buffer
1174 1234 self.text_until_cursor = self.line_buffer[:cursor_pos]
1175 # io.rprint('COMP2 %r %r %r' % (text, line_buffer, cursor_pos)) # dbg
1176 1235
1177 1236 # Start with a clean slate of completions
1178 1237 self.matches[:] = []
@@ -1202,10 +1261,11 b' class IPCompleter(Completer):'
1202 1261 # different types of objects. The rlcomplete() method could then
1203 1262 # simply collapse the dict into a list for readline, but we'd have
1204 1263 # richer completion semantics in other evironments.
1264 if self.use_jedi_completions:
1265 self.matches.extend(self.python_jedi_matches(text, line_buffer, cursor_pos))
1205 1266
1206 1267 self.matches = sorted(set(self.matches), key=completions_sorting_key)
1207 1268
1208 #io.rprint('COMP TEXT, MATCHES: %r, %r' % (text, self.matches)) # dbg
1209 1269 return text, self.matches
1210 1270
1211 1271 def rlcomplete(self, text, state):
@@ -181,7 +181,7 b' def test_no_ascii_back_completion():'
181 181 ip = get_ipython()
182 182 with TemporaryWorkingDirectory(): # Avoid any filename completions
183 183 # single ascii letter that don't have yet completions
184 for letter in 'fjqyJMQVWY' :
184 for letter in 'jJ' :
185 185 name, matches = ip.complete('\\'+letter)
186 186 nt.assert_equal(matches, [])
187 187
@@ -264,19 +264,36 b' def test_local_file_completions():'
264 264 # Now check with a function call
265 265 cmd = 'a = f("%s' % prefix
266 266 c = ip.complete(prefix, cmd)[1]
267 comp = [prefix+s for s in suffixes]
268 nt.assert_equal(c, comp)
267 comp = set(prefix+s for s in suffixes)
268 nt.assert_true(comp.issubset(set(c)))
269 269
270 270
271 271 def test_greedy_completions():
272 272 ip = get_ipython()
273 273 ip.ex('a=list(range(5))')
274 274 _,c = ip.complete('.',line='a[0].')
275 nt.assert_false('a[0].real' in c,
275 nt.assert_false('.real' in c,
276 276 "Shouldn't have completed on a[0]: %s"%c)
277 277 with greedy_completion():
278 _,c = ip.complete('.',line='a[0].')
279 nt.assert_true('a[0].real' in c, "Should have completed on a[0]: %s"%c)
278 def _(line, cursor_pos, expect, message):
279 _,c = ip.complete('.', line=line, cursor_pos=cursor_pos)
280 nt.assert_in(expect, c, message%c)
281
282 yield _, 'a[0].', 5, '.real', "Should have completed on a[0].: %s"
283 yield _, 'a[0].r', 6, '.real', "Should have completed on a[0].r: %s"
284
285 if sys.version_info > (3,4):
286 yield _, 'a[0].from_', 10, '.from_bytes', "Should have completed on a[0].from_: %s"
287
288
289 def _2():
290 # jedi bug, this will be empty, makeitfail for now,
291 # once jedi is fixed, switch to assert_in
292 # https://github.com/davidhalter/jedi/issues/718
293 _,c = ip.complete('.',line='a[0].from', cursor_pos=9)
294 nt.assert_not_in('.from_bytes', c, "Should not have completed on a[0].from (jedi bug), if fails, update test to assert_in: %s"%c)
295 yield _2
296
280 297
281 298
282 299 def test_omit__names():
@@ -321,20 +338,6 b' def test_limit_to__all__False_ok():'
321 338 nt.assert_in('d.x', matches)
322 339
323 340
324 def test_limit_to__all__True_ok():
325 ip = get_ipython()
326 c = ip.Completer
327 ip.ex('class D: x=24')
328 ip.ex('d=D()')
329 ip.ex("d.__all__=['z']")
330 cfg = Config()
331 cfg.IPCompleter.limit_to__all__ = True
332 c.update_config(cfg)
333 s, matches = c.complete('d.')
334 nt.assert_in('d.z', matches)
335 nt.assert_not_in('d.x', matches)
336
337
338 341 def test_get__all__entries_ok():
339 342 class A(object):
340 343 __all__ = ['x', 1]
@@ -366,7 +369,6 b' def test_func_kw_completions():'
366 369
367 370
368 371 def test_default_arguments_from_docstring():
369 doc = min.__doc__
370 372 ip = get_ipython()
371 373 c = ip.Completer
372 374 kwd = c._default_arguments_from_docstring(
@@ -68,9 +68,13 b' class IPythonPTCompleter(Completer):'
68 68 yield Completion(m, start_position=start_pos - 1)
69 69 continue
70 70
71 # TODO: Use Jedi to determine meta_text
72 # (Jedi currently has a bug that results in incorrect information.)
73 # meta_text = ''
74 # yield Completion(m, start_position=start_pos,
75 # display_meta=meta_text)
71 76 yield Completion(m, start_position=start_pos)
72 77
73
74 78 class IPythonPTLexer(Lexer):
75 79 """
76 80 Wrapper around PythonLexer and BashLexer.
@@ -182,7 +182,7 b' extras_require = dict('
182 182 parallel = ['ipyparallel'],
183 183 qtconsole = ['qtconsole'],
184 184 doc = ['Sphinx>=1.3'],
185 test = ['nose>=0.10.1', 'requests', 'testpath', 'pygments'],
185 test = ['nose>=0.10.1', 'requests', 'testpath', 'pygments', 'path.py'],
186 186 terminal = [],
187 187 kernel = ['ipykernel'],
188 188 nbformat = ['nbformat'],
@@ -191,6 +191,7 b' extras_require = dict('
191 191 )
192 192 install_requires = [
193 193 'setuptools>=18.5',
194 'jedi',
194 195 'decorator',
195 196 'pickleshare',
196 197 'simplegeneric>0.8',
General Comments 0
You need to be logged in to leave comments. Login now