From 444c223ac4dcc902b9095366b643f3a9280215c2 Mon Sep 17 00:00:00 2001 From: Thomas A Caswell Date: Mon, 7 Sep 2015 23:55:26 -0400 Subject: [PATCH 1/3] FIX/API: use inspect.signature for python3 This allows functions with keyword-only arguments to have their signatures introspected. Also makes this bit of code 3.6 compatible. This slightly changes the API in python 3 as all of arguments are available for completion, not just the optional ones. --- IPython/core/completer.py | 16 ++++++++++------ 1 file changed, 10 insertions(+), 6 deletions(-) diff --git a/IPython/core/completer.py b/IPython/core/completer.py index 5032aa5fb72..1893a0dc5d6 100644 --- a/IPython/core/completer.py +++ b/IPython/core/completer.py @@ -839,17 +839,21 @@ def _default_arguments(self, obj): # for all others, check if they are __call__able elif hasattr(obj, '__call__'): call_obj = obj.__call__ - ret += self._default_arguments_from_docstring( getattr(call_obj, '__doc__', '')) - try: - args,_,_1,defaults = inspect.getargspec(call_obj) - if defaults: - ret+=args[-len(defaults):] + if PY3: + _keepers = (inspect.Parameter.KEYWORD_ONLY, + inspect.Parameter.POSITIONAL_OR_KEYWORD) + sig = inspect.signature(call_obj) + ret.extend(k for k, v in sig.parameters.items() if + v.kind in _keepers) + else: + args, _, _1, defaults = inspect.getargspec(call_obj) + if defaults: + ret += args[-len(defaults):] except TypeError: pass - return list(set(ret)) def python_func_kw_matches(self,text): From 2ad3e258884d242ec2861244733ac51ed98200ed Mon Sep 17 00:00:00 2001 From: Thomas A Caswell Date: Tue, 8 Sep 2015 00:18:01 -0400 Subject: [PATCH 2/3] FIX: correct handling of built-ins --- IPython/core/completer.py | 20 ++++++++++++-------- 1 file changed, 12 insertions(+), 8 deletions(-) diff --git a/IPython/core/completer.py b/IPython/core/completer.py index 1893a0dc5d6..afc05174c5e 100644 --- a/IPython/core/completer.py +++ b/IPython/core/completer.py @@ -841,24 +841,28 @@ def _default_arguments(self, obj): call_obj = obj.__call__ ret += self._default_arguments_from_docstring( getattr(call_obj, '__doc__', '')) - try: - if PY3: - _keepers = (inspect.Parameter.KEYWORD_ONLY, - inspect.Parameter.POSITIONAL_OR_KEYWORD) + + if PY3: + _keepers = (inspect.Parameter.KEYWORD_ONLY, + inspect.Parameter.POSITIONAL_OR_KEYWORD) + try: sig = inspect.signature(call_obj) ret.extend(k for k, v in sig.parameters.items() if v.kind in _keepers) - else: + except ValueError: + pass + else: + try: args, _, _1, defaults = inspect.getargspec(call_obj) if defaults: ret += args[-len(defaults):] - except TypeError: - pass + except TypeError: + pass return list(set(ret)) def python_func_kw_matches(self,text): """Match named parameters (kwargs) of the last open function""" - + if "." in text: # a parameter cannot be dotted return [] try: regexp = self.__funcParamsRegex From 8a95d9adc56c2e90a32eb901d4891da373da50e5 Mon Sep 17 00:00:00 2001 From: Thomas A Caswell Date: Tue, 8 Sep 2015 11:47:17 -0400 Subject: [PATCH 3/3] MNT: use back-ported signature on py2 --- IPython/core/completer.py | 29 +++++++++++++++-------------- 1 file changed, 15 insertions(+), 14 deletions(-) diff --git a/IPython/core/completer.py b/IPython/core/completer.py index afc05174c5e..4c793b43c17 100644 --- a/IPython/core/completer.py +++ b/IPython/core/completer.py @@ -843,21 +843,22 @@ def _default_arguments(self, obj): getattr(call_obj, '__doc__', '')) if PY3: - _keepers = (inspect.Parameter.KEYWORD_ONLY, - inspect.Parameter.POSITIONAL_OR_KEYWORD) - try: - sig = inspect.signature(call_obj) - ret.extend(k for k, v in sig.parameters.items() if - v.kind in _keepers) - except ValueError: - pass + _keeps = (inspect.Parameter.KEYWORD_ONLY, + inspect.Parameter.POSITIONAL_OR_KEYWORD) + signature = inspect.signature else: - try: - args, _, _1, defaults = inspect.getargspec(call_obj) - if defaults: - ret += args[-len(defaults):] - except TypeError: - pass + import IPython.utils.signatures + _keeps = (IPython.utils.signatures.Parameter.KEYWORD_ONLY, + IPython.utils.signatures.Parameter.POSITIONAL_OR_KEYWORD) + signature = IPython.utils.signatures.signature + + try: + sig = signature(call_obj) + ret.extend(k for k, v in sig.parameters.items() if + v.kind in _keeps) + except ValueError: + pass + return list(set(ret)) def python_func_kw_matches(self,text):