mirror of
https://github.com/davidhalter/jedi.git
synced 2026-01-02 02:03:21 +08:00
multiple values refactoring in params
This commit is contained in:
@@ -1,4 +1,5 @@
|
|||||||
import copy
|
import copy
|
||||||
|
from itertools import chain
|
||||||
|
|
||||||
from jedi._compatibility import unicode
|
from jedi._compatibility import unicode
|
||||||
from jedi.parser import representation as pr
|
from jedi.parser import representation as pr
|
||||||
@@ -80,19 +81,19 @@ def get_params(evaluator, func, var_args):
|
|||||||
non_matching_keys = []
|
non_matching_keys = []
|
||||||
keys_used = set()
|
keys_used = set()
|
||||||
keys_only = False
|
keys_only = False
|
||||||
value = None
|
va_values = None
|
||||||
for param in func.params[start_offset:]:
|
for param in func.params[start_offset:]:
|
||||||
# The value and key can both be null. There, the defaults apply.
|
# The value and key can both be null. There, the defaults apply.
|
||||||
# args / kwargs will just be empty arrays / dicts, respectively.
|
# args / kwargs will just be empty arrays / dicts, respectively.
|
||||||
# Wrong value count is just ignored. If you try to test cases that are
|
# Wrong value count is just ignored. If you try to test cases that are
|
||||||
# not allowed in Python, Jedi will maybe not show any completions.
|
# not allowed in Python, Jedi will maybe not show any completions.
|
||||||
key, value = next(var_arg_iterator, (None, None))
|
key, va_values = next(var_arg_iterator, (None, []))
|
||||||
while key:
|
while key:
|
||||||
keys_only = True
|
keys_only = True
|
||||||
try:
|
try:
|
||||||
key_param = param_dict[unicode(key)]
|
key_param = param_dict[unicode(key)]
|
||||||
except KeyError:
|
except KeyError:
|
||||||
non_matching_keys.append((key, value))
|
non_matching_keys.append((key, va_values))
|
||||||
else:
|
else:
|
||||||
k = unicode(key)
|
k = unicode(key)
|
||||||
if k in keys_used:
|
if k in keys_used:
|
||||||
@@ -103,8 +104,8 @@ def get_params(evaluator, func, var_args):
|
|||||||
else:
|
else:
|
||||||
keys_used.add(k)
|
keys_used.add(k)
|
||||||
result.append(_gen_param_name_copy(func, var_args, key_param,
|
result.append(_gen_param_name_copy(func, var_args, key_param,
|
||||||
values=[value]))
|
values=va_values))
|
||||||
key, value = next(var_arg_iterator, (None, None))
|
key, va_values = next(var_arg_iterator, (None, []))
|
||||||
|
|
||||||
keys = []
|
keys = []
|
||||||
values = []
|
values = []
|
||||||
@@ -113,23 +114,25 @@ def get_params(evaluator, func, var_args):
|
|||||||
if param.stars == 1:
|
if param.stars == 1:
|
||||||
# *args param
|
# *args param
|
||||||
array_type = pr.Array.TUPLE
|
array_type = pr.Array.TUPLE
|
||||||
if value:
|
values += va_values
|
||||||
values.append(value)
|
for key, va_values in var_arg_iterator:
|
||||||
for key, value in var_arg_iterator:
|
|
||||||
# Iterate until a key argument is found.
|
# Iterate until a key argument is found.
|
||||||
if key:
|
if key:
|
||||||
var_arg_iterator.push_back((key, value))
|
var_arg_iterator.push_back((key, va_values))
|
||||||
break
|
break
|
||||||
values.append(value)
|
values += va_values
|
||||||
elif param.stars == 2:
|
elif param.stars == 2:
|
||||||
# **kwargs param
|
# **kwargs param
|
||||||
array_type = pr.Array.DICT
|
array_type = pr.Array.DICT
|
||||||
if non_matching_keys:
|
if non_matching_keys:
|
||||||
keys, values = zip(*non_matching_keys)
|
keys, values = zip(*non_matching_keys)
|
||||||
|
values = list(chain(*values))
|
||||||
non_matching_keys = []
|
non_matching_keys = []
|
||||||
else:
|
else:
|
||||||
# normal param
|
# normal param
|
||||||
if value is None:
|
if va_values:
|
||||||
|
values = va_values
|
||||||
|
else:
|
||||||
if param.assignment_details:
|
if param.assignment_details:
|
||||||
# No value: return the default values.
|
# No value: return the default values.
|
||||||
has_default_value = True
|
has_default_value = True
|
||||||
@@ -147,8 +150,6 @@ def get_params(evaluator, func, var_args):
|
|||||||
m = _error_argument_count(func, len(var_args))
|
m = _error_argument_count(func, len(var_args))
|
||||||
analysis.add(evaluator, 'type-error-too-few-arguments',
|
analysis.add(evaluator, 'type-error-too-few-arguments',
|
||||||
calling_va, message=m)
|
calling_va, message=m)
|
||||||
else:
|
|
||||||
values = [value]
|
|
||||||
|
|
||||||
# Now add to result if it's not one of the previously covered cases.
|
# Now add to result if it's not one of the previously covered cases.
|
||||||
if not has_default_value and (not keys_only or param.stars == 2):
|
if not has_default_value and (not keys_only or param.stars == 2):
|
||||||
@@ -164,16 +165,18 @@ def get_params(evaluator, func, var_args):
|
|||||||
for k in set(param_dict) - keys_used:
|
for k in set(param_dict) - keys_used:
|
||||||
result.append(_gen_param_name_copy(func, var_args, param_dict[k]))
|
result.append(_gen_param_name_copy(func, var_args, param_dict[k]))
|
||||||
|
|
||||||
for key, value in non_matching_keys:
|
for key, va_values in non_matching_keys:
|
||||||
m = "TypeError: %s() got an unexpected keyword argument '%s'." \
|
m = "TypeError: %s() got an unexpected keyword argument '%s'." \
|
||||||
% (func.name, key)
|
% (func.name, key)
|
||||||
analysis.add(evaluator, 'type-error-keyword-argument', value, message=m)
|
for value in va_values:
|
||||||
|
analysis.add(evaluator, 'type-error-keyword-argument', value, message=m)
|
||||||
|
|
||||||
remaining_params = list(var_arg_iterator)
|
remaining_params = list(var_arg_iterator)
|
||||||
if remaining_params:
|
if remaining_params:
|
||||||
m = _error_argument_count(func, len(func.params) + len(remaining_params))
|
m = _error_argument_count(func, len(func.params) + len(remaining_params))
|
||||||
analysis.add(evaluator, 'type-error-too-many-arguments',
|
for p in remaining_params[0][1]:
|
||||||
remaining_params[0][1], message=m)
|
analysis.add(evaluator, 'type-error-too-many-arguments',
|
||||||
|
p, message=m)
|
||||||
return result
|
return result
|
||||||
|
|
||||||
|
|
||||||
@@ -185,7 +188,7 @@ def _var_args_iterator(evaluator, var_args):
|
|||||||
for stmt in var_args:
|
for stmt in var_args:
|
||||||
if not isinstance(stmt, pr.Statement):
|
if not isinstance(stmt, pr.Statement):
|
||||||
if stmt is None:
|
if stmt is None:
|
||||||
yield None, None
|
yield None, []
|
||||||
continue
|
continue
|
||||||
old = stmt
|
old = stmt
|
||||||
# generate a statement if it's not already one.
|
# generate a statement if it's not already one.
|
||||||
@@ -197,13 +200,16 @@ def _var_args_iterator(evaluator, var_args):
|
|||||||
continue
|
continue
|
||||||
if expression_list[0] == '*':
|
if expression_list[0] == '*':
|
||||||
# *args must be some sort of an array, otherwise -> ignore
|
# *args must be some sort of an array, otherwise -> ignore
|
||||||
for array in evaluator.eval_expression_list(expression_list[1:]):
|
arrays = evaluator.eval_expression_list(expression_list[1:])
|
||||||
|
#for array in array[:]:
|
||||||
|
if arrays:
|
||||||
|
array = arrays[0]
|
||||||
if isinstance(array, iterable.Array):
|
if isinstance(array, iterable.Array):
|
||||||
for field_stmt in array: # yield from plz!
|
for field_stmt in array: # yield from plz!
|
||||||
yield None, field_stmt
|
yield None, [field_stmt]
|
||||||
elif isinstance(array, iterable.Generator):
|
elif isinstance(array, iterable.Generator):
|
||||||
for field_stmt in array.iter_content():
|
for field_stmt in array.iter_content():
|
||||||
yield None, helpers.FakeStatement([field_stmt])
|
yield None, [helpers.FakeStatement([field_stmt])]
|
||||||
# **kwargs
|
# **kwargs
|
||||||
elif expression_list[0] == '**':
|
elif expression_list[0] == '**':
|
||||||
for array in evaluator.eval_expression_list(expression_list[1:]):
|
for array in evaluator.eval_expression_list(expression_list[1:]):
|
||||||
@@ -212,18 +218,18 @@ def _var_args_iterator(evaluator, var_args):
|
|||||||
# first index, is the key if syntactically correct
|
# first index, is the key if syntactically correct
|
||||||
call = key_stmt.expression_list()[0]
|
call = key_stmt.expression_list()[0]
|
||||||
if isinstance(call, pr.Name):
|
if isinstance(call, pr.Name):
|
||||||
yield call, value_stmt
|
yield call, [value_stmt]
|
||||||
elif isinstance(call, pr.Call):
|
elif isinstance(call, pr.Call):
|
||||||
yield call.name, value_stmt
|
yield call.name, [value_stmt]
|
||||||
# Normal arguments (including key arguments).
|
# Normal arguments (including key arguments).
|
||||||
else:
|
else:
|
||||||
if stmt.assignment_details:
|
if stmt.assignment_details:
|
||||||
key_arr, op = stmt.assignment_details[0]
|
key_arr, op = stmt.assignment_details[0]
|
||||||
# named parameter
|
# named parameter
|
||||||
if key_arr and isinstance(key_arr[0], pr.Call):
|
if key_arr and isinstance(key_arr[0], pr.Call):
|
||||||
yield key_arr[0].name, stmt
|
yield key_arr[0].name, [stmt]
|
||||||
else:
|
else:
|
||||||
yield None, stmt
|
yield None, [stmt]
|
||||||
|
|
||||||
|
|
||||||
def _gen_param_name_copy(func, var_args, param, keys=(), values=(), array_type=None):
|
def _gen_param_name_copy(func, var_args, param, keys=(), values=(), array_type=None):
|
||||||
|
|||||||
@@ -231,6 +231,17 @@ exe[1]
|
|||||||
#? list()
|
#? list()
|
||||||
exe[1][1]
|
exe[1][1]
|
||||||
|
|
||||||
|
|
||||||
|
# In a dynamic search, both inputs should be given.
|
||||||
|
def simple(a):
|
||||||
|
#? int() str()
|
||||||
|
return a
|
||||||
|
def xargs(*args):
|
||||||
|
return simple(*args)
|
||||||
|
|
||||||
|
xargs(1)
|
||||||
|
xargs('')
|
||||||
|
|
||||||
# -----------------
|
# -----------------
|
||||||
# ** kwargs
|
# ** kwargs
|
||||||
# -----------------
|
# -----------------
|
||||||
|
|||||||
@@ -27,3 +27,17 @@ def nested_twice(*args1):
|
|||||||
return nested(*args1)
|
return nested(*args1)
|
||||||
|
|
||||||
nested_twice(2, 3)
|
nested_twice(2, 3)
|
||||||
|
#! 12 type-error-too-few-arguments
|
||||||
|
nested_twice(2)
|
||||||
|
|
||||||
|
# -----------------
|
||||||
|
# **kwargs
|
||||||
|
# -----------------
|
||||||
|
|
||||||
|
|
||||||
|
def kwargs_test(**kwargs):
|
||||||
|
return simple2(1, **kwargs)
|
||||||
|
|
||||||
|
kwargs_test(c=3, b=2)
|
||||||
|
kwargs_test(c=3)
|
||||||
|
kwargs_test(b=2)
|
||||||
|
|||||||
Reference in New Issue
Block a user