multiple values refactoring in params

This commit is contained in:
Dave Halter
2014-05-29 16:59:56 +02:00
parent 1899f16a4a
commit b24178b275
3 changed files with 56 additions and 25 deletions

View File

@@ -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):

View File

@@ -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
# ----------------- # -----------------

View File

@@ -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)