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 = [ |
|
|
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 ' |
|
|
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 = |
|
|
268 |
nt.assert_ |
|
|
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(' |
|
|
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