mirror of
https://github.com/davidhalter/jedi.git
synced 2025-12-06 22:14:27 +08:00
Deal better with non-functions
This commit is contained in:
@@ -30,7 +30,7 @@ class _SignatureMixin(object):
|
|||||||
s += ' -> ' + annotation
|
s += ' -> ' + annotation
|
||||||
return s
|
return s
|
||||||
|
|
||||||
def get_param_names(self):
|
def get_param_names(self, resolve_stars=True):
|
||||||
param_names = self._function_context.get_param_names()
|
param_names = self._function_context.get_param_names()
|
||||||
if self.is_bound:
|
if self.is_bound:
|
||||||
return param_names[1:]
|
return param_names[1:]
|
||||||
@@ -77,9 +77,12 @@ class TreeSignature(AbstractSignature):
|
|||||||
return ''
|
return ''
|
||||||
return a.get_code(include_prefix=False)
|
return a.get_code(include_prefix=False)
|
||||||
|
|
||||||
def get_param_names(self):
|
def get_param_names(self, resolve_stars=True):
|
||||||
from jedi.evaluate.star_args import process_params
|
params = super(TreeSignature, self).get_param_names()
|
||||||
return process_params(super(TreeSignature, self).get_param_names())
|
if resolve_stars:
|
||||||
|
from jedi.evaluate.star_args import process_params
|
||||||
|
params = process_params(params)
|
||||||
|
return params
|
||||||
|
|
||||||
|
|
||||||
class BuiltinSignature(AbstractSignature):
|
class BuiltinSignature(AbstractSignature):
|
||||||
|
|||||||
@@ -94,8 +94,8 @@ def _remove_given_params(arguments, param_names):
|
|||||||
|
|
||||||
def process_params(param_names, star_count=3): # default means both * and **
|
def process_params(param_names, star_count=3): # default means both * and **
|
||||||
used_names = set()
|
used_names = set()
|
||||||
arg_funcs = []
|
arg_callables = []
|
||||||
kwarg_funcs = []
|
kwarg_callables = []
|
||||||
|
|
||||||
kw_only_names = []
|
kw_only_names = []
|
||||||
kwarg_names = []
|
kwarg_names = []
|
||||||
@@ -104,13 +104,13 @@ def process_params(param_names, star_count=3): # default means both * and **
|
|||||||
kind = p.get_kind()
|
kind = p.get_kind()
|
||||||
if kind == Parameter.VAR_POSITIONAL:
|
if kind == Parameter.VAR_POSITIONAL:
|
||||||
if star_count & 1:
|
if star_count & 1:
|
||||||
arg_funcs = list(_iter_nodes_for_param(p))
|
arg_callables = list(_iter_nodes_for_param(p))
|
||||||
if not arg_funcs:
|
if not arg_callables:
|
||||||
arg_names.append(p)
|
arg_names.append(p)
|
||||||
elif p.get_kind() == Parameter.VAR_KEYWORD:
|
elif p.get_kind() == Parameter.VAR_KEYWORD:
|
||||||
if star_count & 2:
|
if star_count & 2:
|
||||||
kwarg_funcs = list(_iter_nodes_for_param(p))
|
kwarg_callables = list(_iter_nodes_for_param(p))
|
||||||
if not kwarg_funcs:
|
if not kwarg_callables:
|
||||||
kwarg_names.append(p)
|
kwarg_names.append(p)
|
||||||
elif kind == Parameter.KEYWORD_ONLY:
|
elif kind == Parameter.KEYWORD_ONLY:
|
||||||
if star_count & 2:
|
if star_count & 2:
|
||||||
@@ -128,30 +128,31 @@ def process_params(param_names, star_count=3): # default means both * and **
|
|||||||
yield p
|
yield p
|
||||||
|
|
||||||
longest_param_names = ()
|
longest_param_names = ()
|
||||||
for func_and_argument in arg_funcs:
|
for func_and_argument in arg_callables:
|
||||||
func, arguments = func_and_argument
|
func, arguments = func_and_argument
|
||||||
new_star_count = star_count
|
new_star_count = star_count
|
||||||
if func_and_argument in kwarg_funcs:
|
if func_and_argument in kwarg_callables:
|
||||||
kwarg_funcs.remove(func_and_argument)
|
kwarg_callables.remove(func_and_argument)
|
||||||
else:
|
else:
|
||||||
new_star_count = 1
|
new_star_count = 1
|
||||||
|
|
||||||
args_for_this_func = []
|
for signature in func.get_signatures():
|
||||||
for p in process_params(
|
args_for_this_func = []
|
||||||
list(_remove_given_params(
|
for p in process_params(
|
||||||
arguments,
|
list(_remove_given_params(
|
||||||
func.get_param_names()
|
arguments,
|
||||||
)), new_star_count):
|
signature.get_param_names(resolve_stars=False)
|
||||||
if p.get_kind() == Parameter.VAR_KEYWORD:
|
)), new_star_count):
|
||||||
kwarg_names.append(p)
|
if p.get_kind() == Parameter.VAR_KEYWORD:
|
||||||
elif p.get_kind() == Parameter.VAR_POSITIONAL:
|
kwarg_names.append(p)
|
||||||
arg_names.append(p)
|
elif p.get_kind() == Parameter.VAR_POSITIONAL:
|
||||||
elif p.get_kind() == Parameter.KEYWORD_ONLY:
|
arg_names.append(p)
|
||||||
kw_only_names.append(p)
|
elif p.get_kind() == Parameter.KEYWORD_ONLY:
|
||||||
else:
|
kw_only_names.append(p)
|
||||||
args_for_this_func.append(p)
|
else:
|
||||||
if len(args_for_this_func) > len(longest_param_names):
|
args_for_this_func.append(p)
|
||||||
longest_param_names = args_for_this_func
|
if len(args_for_this_func) > len(longest_param_names):
|
||||||
|
longest_param_names = args_for_this_func
|
||||||
|
|
||||||
for p in longest_param_names:
|
for p in longest_param_names:
|
||||||
if star_count == 1 and p.get_kind() != Parameter.VAR_POSITIONAL:
|
if star_count == 1 and p.get_kind() != Parameter.VAR_POSITIONAL:
|
||||||
@@ -170,14 +171,15 @@ def process_params(param_names, star_count=3): # default means both * and **
|
|||||||
yield p
|
yield p
|
||||||
used_names.add(p.string_name)
|
used_names.add(p.string_name)
|
||||||
|
|
||||||
for func, arguments in kwarg_funcs:
|
for func, arguments in kwarg_callables:
|
||||||
for p in process_params(
|
for signature in func.get_signatures():
|
||||||
list(_remove_given_params(
|
for p in process_params(
|
||||||
arguments,
|
list(_remove_given_params(
|
||||||
func.get_param_names()
|
arguments,
|
||||||
)), star_count=2):
|
signature.get_param_names(resolve_stars=False)
|
||||||
if p.get_kind() != Parameter.KEYWORD_ONLY or not kwarg_names:
|
)), star_count=2):
|
||||||
yield p
|
if p.get_kind() != Parameter.KEYWORD_ONLY or not kwarg_names:
|
||||||
|
yield p
|
||||||
|
|
||||||
if kwarg_names:
|
if kwarg_names:
|
||||||
yield kwarg_names[0]
|
yield kwarg_names[0]
|
||||||
|
|||||||
@@ -94,8 +94,21 @@ def test_tree_signature(Script, environment, code, expected):
|
|||||||
|
|
||||||
@pytest.mark.parametrize(
|
@pytest.mark.parametrize(
|
||||||
'combination, expected', [
|
'combination, expected', [
|
||||||
|
# Functions
|
||||||
('full_redirect(simple)', 'b, *, c'),
|
('full_redirect(simple)', 'b, *, c'),
|
||||||
|
('full_redirect(simple4)', 'b, x: int'),
|
||||||
|
('full_redirect(a)', 'b, *args'),
|
||||||
|
('full_redirect(kw)', 'b, *, c, **kwargs'),
|
||||||
|
('full_redirect(akw)', 'c, *args, **kwargs'),
|
||||||
|
|
||||||
|
# Non functions
|
||||||
|
('full_redirect(lambda x, y: ...)', 'y'),
|
||||||
|
('full_redirect(C)', 'z, *c'),
|
||||||
|
('full_redirect(C())', 'y'),
|
||||||
|
('full_redirect()', '*args, **kwargs'),
|
||||||
|
('full_redirect(1)', '*args, **kwargs'),
|
||||||
|
|
||||||
|
# Merging
|
||||||
('two_redirects(simple, simple)', 'a, b, *, c'),
|
('two_redirects(simple, simple)', 'a, b, *, c'),
|
||||||
('two_redirects(simple2, simple2)', 'x'),
|
('two_redirects(simple2, simple2)', 'x'),
|
||||||
('two_redirects(akw, kw)', 'a, c, *args, **kwargs'),
|
('two_redirects(akw, kw)', 'a, c, *args, **kwargs'),
|
||||||
@@ -145,6 +158,10 @@ def test_nested_signatures(Script, environment, combination, expected):
|
|||||||
return lambda *args, **kwargs: func1(*args) + func2(**kwargs)
|
return lambda *args, **kwargs: func1(*args) + func2(**kwargs)
|
||||||
def combined_lot_of_args(func1, func2):
|
def combined_lot_of_args(func1, func2):
|
||||||
return lambda *args, **kwargs: func1(1, 2, 3, 4, *args) + func2(a=3, x=1, y=1, **kwargs)
|
return lambda *args, **kwargs: func1(1, 2, 3, 4, *args) + func2(a=3, x=1, y=1, **kwargs)
|
||||||
|
|
||||||
|
class C:
|
||||||
|
def __init__(self, a, z, *c): ...
|
||||||
|
def __call__(self, x, y): ...
|
||||||
''')
|
''')
|
||||||
code += 'z = ' + combination + '\nz('
|
code += 'z = ' + combination + '\nz('
|
||||||
sig, = Script(code).call_signatures()
|
sig, = Script(code).call_signatures()
|
||||||
|
|||||||
Reference in New Issue
Block a user