##// END OF EJS Templates
Initial patch with Jedi completion (no function header description)....
Kelly Liu -
Show More
@@ -53,6 +53,8 b' Notes:'
53 # Some of this code originated from rlcompleter in the Python standard library
53 # Some of this code originated from rlcompleter in the Python standard library
54 # Copyright (C) 2001 Python Software Foundation, www.python.org
54 # Copyright (C) 2001 Python Software Foundation, www.python.org
55
55
56 from __future__ import print_function
57
56 import __main__
58 import __main__
57 import glob
59 import glob
58 import inspect
60 import inspect
@@ -76,6 +78,14 b' from IPython.utils.process import arg_split'
76 from IPython.utils.py3compat import builtin_mod, string_types, PY3
78 from IPython.utils.py3compat import builtin_mod, string_types, PY3
77 from traitlets import CBool, Enum
79 from traitlets import CBool, Enum
78
80
81 try:
82 import jedi
83 import jedi.api.helpers
84 import jedi.parser.user_context
85 JEDI_INSTALLED = True
86 except ImportError:
87 JEDI_INSTALLED = False
88
79 #-----------------------------------------------------------------------------
89 #-----------------------------------------------------------------------------
80 # Globals
90 # Globals
81 #-----------------------------------------------------------------------------
91 #-----------------------------------------------------------------------------
@@ -267,6 +277,7 b' class Completer(Configurable):'
267
277
268 greedy = CBool(False, config=True,
278 greedy = CBool(False, config=True,
269 help="""Activate greedy completion
279 help="""Activate greedy completion
280 PENDING DEPRECTION. this is now mostly taken care of with Jedi.
270
281
271 This will enable completion on elements of lists, results of function calls, etc.,
282 This will enable completion on elements of lists, results of function calls, etc.,
272 but can be unsafe because the code is actually evaluated on TAB.
283 but can be unsafe because the code is actually evaluated on TAB.
@@ -277,7 +288,7 b' class Completer(Configurable):'
277 def __init__(self, namespace=None, global_namespace=None, **kwargs):
288 def __init__(self, namespace=None, global_namespace=None, **kwargs):
278 """Create a new completer for the command line.
289 """Create a new completer for the command line.
279
290
280 Completer(namespace=ns,global_namespace=ns2) -> completer instance.
291 Completer(namespace=ns, global_namespace=ns2) -> completer instance.
281
292
282 If unspecified, the default namespace where completions are performed
293 If unspecified, the default namespace where completions are performed
283 is __main__ (technically, __main__.__dict__). Namespaces should be
294 is __main__ (technically, __main__.__dict__). Namespaces should be
@@ -337,7 +348,6 b' class Completer(Configurable):'
337 defined in self.namespace or self.global_namespace that match.
348 defined in self.namespace or self.global_namespace that match.
338
349
339 """
350 """
340 #print 'Completer->global_matches, txt=%r' % text # dbg
341 matches = []
351 matches = []
342 match_append = matches.append
352 match_append = matches.append
343 n = len(text)
353 n = len(text)
@@ -364,7 +374,6 b' class Completer(Configurable):'
364
374
365 """
375 """
366
376
367 #io.rprint('Completer->attr_matches, txt=%r' % text) # dbg
368 # Another option, seems to work great. Catches things like ''.<tab>
377 # Another option, seems to work great. Catches things like ''.<tab>
369 m = re.match(r"(\S+(\.\w+)*)\.(\w*)$", text)
378 m = re.match(r"(\S+(\.\w+)*)\.(\w*)$", text)
370
379
@@ -564,7 +573,10 b' class IPCompleter(Completer):'
564 """
573 """
565 )
574 )
566 limit_to__all__ = CBool(default_value=False, config=True,
575 limit_to__all__ = CBool(default_value=False, config=True,
567 help="""Instruct the completer to use __all__ for the completion
576 help="""
577 DEPRECATED as of version 5.0.
578
579 Instruct the completer to use __all__ for the completion
568
580
569 Specifically, when completing on ``object.<tab>``.
581 Specifically, when completing on ``object.<tab>``.
570
582
@@ -573,6 +585,9 b' class IPCompleter(Completer):'
573 When False [default]: the __all__ attribute is ignored
585 When False [default]: the __all__ attribute is ignored
574 """
586 """
575 )
587 )
588 use_jedi_completions = CBool(default_value=JEDI_INSTALLED, config=True,
589 help="""Use Jedi to generate autocompletions.
590 """)
576
591
577 def __init__(self, shell=None, namespace=None, global_namespace=None,
592 def __init__(self, shell=None, namespace=None, global_namespace=None,
578 use_readline=True, config=None, **kwargs):
593 use_readline=True, config=None, **kwargs):
@@ -639,7 +654,7 b' class IPCompleter(Completer):'
639 #= re.compile(r'[\s|\[]*(\w+)(?:\s*=?\s*.*)')
654 #= re.compile(r'[\s|\[]*(\w+)(?:\s*=?\s*.*)')
640
655
641 # All active matcher routines for completion
656 # All active matcher routines for completion
642 self.matchers = [self.python_matches,
657 self.matchers = [
643 self.file_matches,
658 self.file_matches,
644 self.magic_matches,
659 self.magic_matches,
645 self.python_func_kw_matches,
660 self.python_func_kw_matches,
@@ -653,7 +668,7 b' class IPCompleter(Completer):'
653 """
668 """
654 return self.complete(text)[1]
669 return self.complete(text)[1]
655
670
656 def _clean_glob(self,text):
671 def _clean_glob(self, text):
657 return self.glob("%s*" % text)
672 return self.glob("%s*" % text)
658
673
659 def _clean_glob_win32(self,text):
674 def _clean_glob_win32(self,text):
@@ -674,8 +689,6 b' class IPCompleter(Completer):'
674 current (as of Python 2.3) Python readline it's possible to do
689 current (as of Python 2.3) Python readline it's possible to do
675 better."""
690 better."""
676
691
677 #io.rprint('Completer->file_matches: <%r>' % text) # dbg
678
679 # chars that require escaping with backslash - i.e. chars
692 # chars that require escaping with backslash - i.e. chars
680 # that readline treats incorrectly as delimiters, but we
693 # that readline treats incorrectly as delimiters, but we
681 # don't want to treat as delimiters in filename matching
694 # don't want to treat as delimiters in filename matching
@@ -737,15 +750,12 b' class IPCompleter(Completer):'
737 matches = [text_prefix +
750 matches = [text_prefix +
738 protect_filename(f) for f in m0]
751 protect_filename(f) for f in m0]
739
752
740 #io.rprint('mm', matches) # dbg
741
742 # Mark directories in input list by appending '/' to their names.
753 # Mark directories in input list by appending '/' to their names.
743 matches = [x+'/' if os.path.isdir(x) else x for x in matches]
754 matches = [x+'/' if os.path.isdir(x) else x for x in matches]
744 return matches
755 return matches
745
756
746 def magic_matches(self, text):
757 def magic_matches(self, text):
747 """Match magics"""
758 """Match magics"""
748 #print 'Completer->magic_matches:',text,'lb',self.text_until_cursor # dbg
749 # Get all shell magics now rather than statically, so magics loaded at
759 # Get all shell magics now rather than statically, so magics loaded at
750 # runtime show up too.
760 # runtime show up too.
751 lsm = self.shell.magics_manager.lsmagic()
761 lsm = self.shell.magics_manager.lsmagic()
@@ -765,10 +775,62 b' class IPCompleter(Completer):'
765 comp += [ pre+m for m in line_magics if m.startswith(bare_text)]
775 comp += [ pre+m for m in line_magics if m.startswith(bare_text)]
766 return comp
776 return comp
767
777
768 def python_matches(self,text):
778 def python_jedi_matches(self, text, line_buffer, cursor_pos):
769 """Match attributes or global python names"""
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
770
812
771 #io.rprint('Completer->python_matches, txt=%r' % text) # dbg
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
830 def python_matches(self, text):
831 """Match attributes or global python names"""
832 # Jedi completion
833
772 if "." in text:
834 if "." in text:
773 try:
835 try:
774 matches = self.attr_matches(text)
836 matches = self.attr_matches(text)
@@ -1075,7 +1137,6 b' class IPCompleter(Completer):'
1075 return u'', []
1137 return u'', []
1076
1138
1077 def dispatch_custom_completer(self, text):
1139 def dispatch_custom_completer(self, text):
1078 #io.rprint("Custom! '%s' %s" % (text, self.custom_completers)) # dbg
1079 line = self.line_buffer
1140 line = self.line_buffer
1080 if not line.strip():
1141 if not line.strip():
1081 return None
1142 return None
@@ -1089,8 +1150,6 b' class IPCompleter(Completer):'
1089 event.command = cmd
1150 event.command = cmd
1090 event.text_until_cursor = self.text_until_cursor
1151 event.text_until_cursor = self.text_until_cursor
1091
1152
1092 #print "\ncustom:{%s]\n" % event # dbg
1093
1094 # for foo etc, try also to find completer for %foo
1153 # for foo etc, try also to find completer for %foo
1095 if not cmd.startswith(self.magic_escape):
1154 if not cmd.startswith(self.magic_escape):
1096 try_magic = self.custom_completers.s_matches(
1155 try_magic = self.custom_completers.s_matches(
@@ -1101,7 +1160,6 b' class IPCompleter(Completer):'
1101 for c in itertools.chain(self.custom_completers.s_matches(cmd),
1160 for c in itertools.chain(self.custom_completers.s_matches(cmd),
1102 try_magic,
1161 try_magic,
1103 self.custom_completers.flat_matches(self.text_until_cursor)):
1162 self.custom_completers.flat_matches(self.text_until_cursor)):
1104 #print "try",c # dbg
1105 try:
1163 try:
1106 res = c(event)
1164 res = c(event)
1107 if res:
1165 if res:
@@ -1147,8 +1205,6 b' class IPCompleter(Completer):'
1147 matches : list
1205 matches : list
1148 A list of completion matches.
1206 A list of completion matches.
1149 """
1207 """
1150 # io.rprint('\nCOMP1 %r %r %r' % (text, line_buffer, cursor_pos)) # dbg
1151
1152 # if the cursor position isn't given, the only sane assumption we can
1208 # if the cursor position isn't given, the only sane assumption we can
1153 # make is that it's at the end of the line (the common case)
1209 # make is that it's at the end of the line (the common case)
1154 if cursor_pos is None:
1210 if cursor_pos is None:
@@ -1177,7 +1233,6 b' class IPCompleter(Completer):'
1177
1233
1178 self.line_buffer = line_buffer
1234 self.line_buffer = line_buffer
1179 self.text_until_cursor = self.line_buffer[:cursor_pos]
1235 self.text_until_cursor = self.line_buffer[:cursor_pos]
1180 # io.rprint('COMP2 %r %r %r' % (text, line_buffer, cursor_pos)) # dbg
1181
1236
1182 # Start with a clean slate of completions
1237 # Start with a clean slate of completions
1183 self.matches[:] = []
1238 self.matches[:] = []
@@ -1207,10 +1262,11 b' class IPCompleter(Completer):'
1207 # different types of objects. The rlcomplete() method could then
1262 # different types of objects. The rlcomplete() method could then
1208 # simply collapse the dict into a list for readline, but we'd have
1263 # simply collapse the dict into a list for readline, but we'd have
1209 # richer completion semantics in other evironments.
1264 # richer completion semantics in other evironments.
1265 if self.use_jedi_completions:
1266 self.matches.extend(self.python_jedi_matches(text, line_buffer, cursor_pos))
1210
1267
1211 self.matches = sorted(set(self.matches), key=completions_sorting_key)
1268 self.matches = sorted(set(self.matches), key=completions_sorting_key)
1212
1269
1213 #io.rprint('COMP TEXT, MATCHES: %r, %r' % (text, self.matches)) # dbg
1214 return text, self.matches
1270 return text, self.matches
1215
1271
1216 def rlcomplete(self, text, state):
1272 def rlcomplete(self, text, state):
@@ -181,7 +181,7 b' def test_no_ascii_back_completion():'
181 ip = get_ipython()
181 ip = get_ipython()
182 with TemporaryWorkingDirectory(): # Avoid any filename completions
182 with TemporaryWorkingDirectory(): # Avoid any filename completions
183 # single ascii letter that don't have yet completions
183 # single ascii letter that don't have yet completions
184 for letter in 'fjqyJMQVWY' :
184 for letter in 'jJ' :
185 name, matches = ip.complete('\\'+letter)
185 name, matches = ip.complete('\\'+letter)
186 nt.assert_equal(matches, [])
186 nt.assert_equal(matches, [])
187
187
@@ -264,19 +264,36 b' def test_local_file_completions():'
264 # Now check with a function call
264 # Now check with a function call
265 cmd = 'a = f("%s' % prefix
265 cmd = 'a = f("%s' % prefix
266 c = ip.complete(prefix, cmd)[1]
266 c = ip.complete(prefix, cmd)[1]
267 comp = [prefix+s for s in suffixes]
267 comp = set(prefix+s for s in suffixes)
268 nt.assert_equal(c, comp)
268 nt.assert_true(comp.issubset(set(c)))
269
269
270
270
271 def test_greedy_completions():
271 def test_greedy_completions():
272 ip = get_ipython()
272 ip = get_ipython()
273 ip.ex('a=list(range(5))')
273 ip.ex('a=list(range(5))')
274 _,c = ip.complete('.',line='a[0].')
274 _,c = ip.complete('.',line='a[0].')
275 nt.assert_false('a[0].real' in c,
275 nt.assert_false('.real' in c,
276 "Shouldn't have completed on a[0]: %s"%c)
276 "Shouldn't have completed on a[0]: %s"%c)
277 with greedy_completion():
277 with greedy_completion():
278 _,c = ip.complete('.',line='a[0].')
278 def _(line, cursor_pos, expect, message):
279 nt.assert_true('a[0].real' in c, "Should have completed on a[0]: %s"%c)
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 def test_omit__names():
299 def test_omit__names():
@@ -321,20 +338,6 b' def test_limit_to__all__False_ok():'
321 nt.assert_in('d.x', matches)
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 def test_get__all__entries_ok():
341 def test_get__all__entries_ok():
339 class A(object):
342 class A(object):
340 __all__ = ['x', 1]
343 __all__ = ['x', 1]
@@ -366,7 +369,6 b' def test_func_kw_completions():'
366
369
367
370
368 def test_default_arguments_from_docstring():
371 def test_default_arguments_from_docstring():
369 doc = min.__doc__
370 ip = get_ipython()
372 ip = get_ipython()
371 c = ip.Completer
373 c = ip.Completer
372 kwd = c._default_arguments_from_docstring(
374 kwd = c._default_arguments_from_docstring(
@@ -783,6 +785,12 b' def test_aimport_module_completer():'
783 nt.assert_in('io', matches)
785 nt.assert_in('io', matches)
784 nt.assert_not_in('int', matches)
786 nt.assert_not_in('int', matches)
785
787
788 def test_nested_import_module_completer():
789 ip = get_ipython()
790 _, matches = ip.complete(None, 'import IPython.co', 17)
791 nt.assert_in('IPython.core', matches)
792 nt.assert_not_in('import IPython.core', matches)
793
786 def test_import_module_completer():
794 def test_import_module_completer():
787 ip = get_ipython()
795 ip = get_ipython()
788 _, matches = ip.complete('i', 'import i')
796 _, matches = ip.complete('i', 'import i')
@@ -49,9 +49,13 b' class IPythonPTCompleter(Completer):'
49 )
49 )
50 start_pos = -len(used)
50 start_pos = -len(used)
51 for m in matches:
51 for m in matches:
52 # TODO: Use Jedi to determine meta_text
53 # (Jedi currently has a bug that results in incorrect information.)
54 # meta_text = ''
55 # yield Completion(m, start_position=start_pos,
56 # display_meta=meta_text)
52 yield Completion(m, start_position=start_pos)
57 yield Completion(m, start_position=start_pos)
53
58
54
55 class IPythonPTLexer(Lexer):
59 class IPythonPTLexer(Lexer):
56 """
60 """
57 Wrapper around PythonLexer and BashLexer.
61 Wrapper around PythonLexer and BashLexer.
@@ -182,7 +182,7 b' extras_require = dict('
182 parallel = ['ipyparallel'],
182 parallel = ['ipyparallel'],
183 qtconsole = ['qtconsole'],
183 qtconsole = ['qtconsole'],
184 doc = ['Sphinx>=1.3'],
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 terminal = [],
186 terminal = [],
187 kernel = ['ipykernel'],
187 kernel = ['ipykernel'],
188 nbformat = ['nbformat'],
188 nbformat = ['nbformat'],
@@ -191,6 +191,7 b' extras_require = dict('
191 )
191 )
192 install_requires = [
192 install_requires = [
193 'setuptools>=18.5',
193 'setuptools>=18.5',
194 'jedi',
194 'decorator',
195 'decorator',
195 'pickleshare',
196 'pickleshare',
196 'simplegeneric>0.8',
197 'simplegeneric>0.8',
General Comments 0
You need to be logged in to leave comments. Login now