##// END OF EJS Templates
Merge pull request #2599 from piti118/docstring_keyword...
Min RK -
r9435:918365c1 merge
parent child Browse files
Show More
@@ -496,6 +496,12 b' class IPCompleter(Completer):'
496 496 else:
497 497 self.clean_glob = self._clean_glob
498 498
499 #regexp to parse docstring for function signature
500 self.docstring_sig_re = re.compile(r'^[\w|\s.]+\(([^)]*)\).*')
501 self.docstring_kwd_re = re.compile(r'[\s|\[]*(\w+)(?:\s*=\s*.*)')
502 #use this if positional argument name is also needed
503 #= re.compile(r'[\s|\[]*(\w+)(?:\s*=?\s*.*)')
504
499 505 # All active matcher routines for completion
500 506 self.matchers = [self.python_matches,
501 507 self.file_matches,
@@ -664,29 +670,67 b' class IPCompleter(Completer):'
664 670
665 671 return matches
666 672
673 def _default_arguments_from_docstring(self, doc):
674 """Parse the first line of docstring for call signature.
675
676 Docstring should be of the form 'min(iterable[, key=func])\n'.
677 It can also parse cython docstring of the form
678 'Minuit.migrad(self, int ncall=10000, resume=True, int nsplit=1)'.
679 """
680 if doc is None:
681 return []
682
683 #care only the firstline
684 line = doc.lstrip().splitlines()[0]
685
686 #p = re.compile(r'^[\w|\s.]+\(([^)]*)\).*')
687 #'min(iterable[, key=func])\n' -> 'iterable[, key=func]'
688 sig = self.docstring_sig_re.search(line)
689 if sig is None:
690 return []
691 # iterable[, key=func]' -> ['iterable[' ,' key=func]']
692 sig = sig.groups()[0].split(',')
693 ret = []
694 for s in sig:
695 #re.compile(r'[\s|\[]*(\w+)(?:\s*=\s*.*)')
696 ret += self.docstring_kwd_re.findall(s)
697 return ret
698
667 699 def _default_arguments(self, obj):
668 700 """Return the list of default arguments of obj if it is callable,
669 701 or empty list otherwise."""
670
671 if not (inspect.isfunction(obj) or inspect.ismethod(obj)):
672 # for classes, check for __init__,__new__
702 call_obj = obj
703 ret = []
704 if inspect.isbuiltin(obj):
705 pass
706 elif not (inspect.isfunction(obj) or inspect.ismethod(obj)):
673 707 if inspect.isclass(obj):
674 obj = (getattr(obj,'__init__',None) or
675 getattr(obj,'__new__',None))
708 #for cython embededsignature=True the constructor docstring
709 #belongs to the object itself not __init__
710 ret += self._default_arguments_from_docstring(
711 getattr(obj, '__doc__', ''))
712 # for classes, check for __init__,__new__
713 call_obj = (getattr(obj, '__init__', None) or
714 getattr(obj, '__new__', None))
676 715 # for all others, check if they are __call__able
677 716 elif hasattr(obj, '__call__'):
678 obj = obj.__call__
679 # XXX: is there a way to handle the builtins ?
717 call_obj = obj.__call__
718
719 ret += self._default_arguments_from_docstring(
720 getattr(call_obj, '__doc__', ''))
721
680 722 try:
681 args,_,_1,defaults = inspect.getargspec(obj)
723 args,_,_1,defaults = inspect.getargspec(call_obj)
682 724 if defaults:
683 return args[-len(defaults):]
684 except TypeError: pass
685 return []
725 ret+=args[-len(defaults):]
726 except TypeError:
727 pass
728
729 return list(set(ret))
686 730
687 731 def python_func_kw_matches(self,text):
688 732 """Match named parameters (kwargs) of the last open function"""
689
733
690 734 if "." in text: # a parameter cannot be dotted
691 735 return []
692 736 try: regexp = self.__funcParamsRegex
@@ -703,6 +747,7 b' class IPCompleter(Completer):'
703 747 tokens = regexp.findall(self.text_until_cursor)
704 748 tokens.reverse()
705 749 iterTokens = iter(tokens); openPar = 0
750
706 751 for token in iterTokens:
707 752 if token == ')':
708 753 openPar -= 1
@@ -716,6 +761,7 b' class IPCompleter(Completer):'
716 761 # 2. Concatenate dotted names ("foo.bar" for "foo.bar(x, pa" )
717 762 ids = []
718 763 isId = re.compile(r'\w+$').match
764
719 765 while True:
720 766 try:
721 767 ids.append(next(iterTokens))
@@ -735,9 +781,10 b' class IPCompleter(Completer):'
735 781 for callableMatch in callableMatches:
736 782 try:
737 783 namedArgs = self._default_arguments(eval(callableMatch,
738 self.namespace))
784 self.namespace))
739 785 except:
740 786 continue
787
741 788 for namedArg in namedArgs:
742 789 if namedArg.startswith(text):
743 790 argMatches.append("%s=" %namedArg)
@@ -288,12 +288,31 b' def test_func_kw_completions():'
288 288 s, matches = c.complete(None, 'myfunc(1,b')
289 289 nt.assert_in('b=', matches)
290 290 # Simulate completing with cursor right after b (pos==10):
291 s, matches = c.complete(None,'myfunc(1,b)', 10)
291 s, matches = c.complete(None, 'myfunc(1,b)', 10)
292 292 nt.assert_in('b=', matches)
293 s, matches = c.complete(None,'myfunc(a="escaped\\")string",b')
293 s, matches = c.complete(None, 'myfunc(a="escaped\\")string",b')
294 294 nt.assert_in('b=', matches)
295 #builtin function
296 s, matches = c.complete(None, 'min(k, k')
297 nt.assert_in('key=', matches)
295 298
296 299
300 def test_default_arguments_from_docstring():
301 doc = min.__doc__
302 ip = get_ipython()
303 c = ip.Completer
304 kwd = c._default_arguments_from_docstring(
305 'min(iterable[, key=func]) -> value')
306 nt.assert_equal(kwd, ['key'])
307 #with cython type etc
308 kwd = c._default_arguments_from_docstring(
309 'Minuit.migrad(self, int ncall=10000, resume=True, int nsplit=1)\n')
310 nt.assert_equal(kwd, ['ncall', 'resume', 'nsplit'])
311 #white spaces
312 kwd = c._default_arguments_from_docstring(
313 '\n Minuit.migrad(self, int ncall=10000, resume=True, int nsplit=1)\n')
314 nt.assert_equal(kwd, ['ncall', 'resume', 'nsplit'])
315
297 316 def test_line_magics():
298 317 ip = get_ipython()
299 318 c = ip.Completer
General Comments 0
You need to be logged in to leave comments. Login now