1
0
forked from VimPlug/jedi

Fix signatures for wraps, see #1058

This commit is contained in:
Dave Halter
2019-07-29 00:12:58 +02:00
parent f6808a96e0
commit fa0424cfd6
3 changed files with 80 additions and 7 deletions

View File

@@ -30,12 +30,6 @@ class _SignatureMixin(object):
s += ' -> ' + annotation s += ' -> ' + annotation
return s return s
def get_param_names(self, resolve_stars=True):
param_names = self._function_context.get_param_names()
if self.is_bound:
return param_names[1:]
return param_names
class AbstractSignature(_SignatureMixin): class AbstractSignature(_SignatureMixin):
def __init__(self, context, is_bound=False): def __init__(self, context, is_bound=False):
@@ -50,6 +44,12 @@ class AbstractSignature(_SignatureMixin):
def annotation_string(self): def annotation_string(self):
return '' return ''
def get_param_names(self, resolve_stars=True):
param_names = self._function_context.get_param_names()
if self.is_bound:
return param_names[1:]
return param_names
def bind(self, context): def bind(self, context):
raise NotImplementedError raise NotImplementedError

View File

@@ -642,6 +642,43 @@ class ItemGetterCallable(ContextWrapper):
return context_set return context_set
@argument_clinic('func, /')
def _functools_wraps(funcs):
return ContextSet(WrapsCallable(func) for func in funcs)
class WrapsCallable(ContextWrapper):
@repack_with_argument_clinic('func, /')
def py__call__(self, funcs):
return ContextSet({Wrapped(func, self._wrapped_context) for func in funcs})
class Wrapped(ContextWrapper):
def __init__(self, func, original_function):
super(Wrapped, self).__init__(func)
self._original_function = original_function
@property
def name(self):
return self._original_function.name
def get_signatures(self):
return [
ReplacedNameSignature(sig, self._original_function.name)
for sig in self._wrapped_context.get_signatures()
]
class ReplacedNameSignature(SignatureWrapper):
def __init__(self, signature, name):
super(ReplacedNameSignature, self).__init__(signature)
self._name = name
@property
def name(self):
return self._name
@argument_clinic('*args, /', want_obj=True, want_arguments=True) @argument_clinic('*args, /', want_obj=True, want_arguments=True)
def _operator_itemgetter(args_context_set, obj, arguments): def _operator_itemgetter(args_context_set, obj, arguments):
return ContextSet([ return ContextSet([
@@ -675,7 +712,8 @@ _implemented = {
}, },
'functools': { 'functools': {
'partial': functools_partial, 'partial': functools_partial,
'wraps': _return_first_param, 'wraps': _functools_wraps,
#'wraps': _return_first_param,
}, },
'_weakref': { '_weakref': {
'proxy': _return_first_param, 'proxy': _return_first_param,

View File

@@ -179,6 +179,41 @@ def test_pow_signature(Script):
'pow(x: int, y: int, /) -> Any'} 'pow(x: int, y: int, /) -> Any'}
@pytest.mark.parametrize(
'code, signature', [
[dedent('''
import functools
def f(x):
pass
def x(f):
@functools.wraps(f)
def wrapper(*args):
# Have no arguments here, but because of wraps, the signature
# should still be f's.
return f(*args)
return wrapper
x(f)('''), 'f(x, /)'],
[dedent('''
import functools
def f(x):
pass
def x(f):
@functools.wraps(f)
def wrapper():
# Have no arguments here, but because of wraps, the signature
# should still be f's.
return 1
return wrapper
x(f)('''), 'f()'],
]
)
def test_wraps_signature(Script, code, signature, skip_pre_python35):
sigs = Script(code).call_signatures()
assert {sig._signature.to_string() for sig in sigs} == {signature}
@pytest.mark.parametrize( @pytest.mark.parametrize(
'start, start_params', [ 'start, start_params', [
['@dataclass\nclass X:', []], ['@dataclass\nclass X:', []],