diff --git a/jedi/evaluate/iterable.py b/jedi/evaluate/iterable.py index 5730170d..ed5bad3d 100644 --- a/jedi/evaluate/iterable.py +++ b/jedi/evaluate/iterable.py @@ -119,7 +119,7 @@ class GeneratorComprehension(Generator): return self._evaluator.eval_statement_element(self.comprehension) -class Array(use_metaclass(CachedMetaClass, IterableWrapper)): +class Array(IterableWrapper): """ Used as a mirror to pr.Array, if needed. It defines some getter methods which are important in this module. @@ -208,7 +208,7 @@ class Array(use_metaclass(CachedMetaClass, IterableWrapper)): def _values(self): if self.type == pr.Array.DICT: - return [v for k, v in self._items()] + return list(chain.from_iterable(v for k, v in self._items())) else: return self._items() @@ -223,7 +223,7 @@ class Array(use_metaclass(CachedMetaClass, IterableWrapper)): if op is None or op == ',': kv.append(key) # A set. elif op == ':': # A dict. - kv.append((key, next(iterator))) + kv.append((key, [next(iterator)])) next(iterator, None) # Possible comma. else: raise NotImplementedError('dict/set comprehensions') @@ -251,6 +251,19 @@ class FakeSequence(Array): for v in self._sequence_values[index])) +class FakeDict(Array): + def __init__(self, evaluator, dct): + super(FakeDict, self).__init__(evaluator, None, pr.Array.DICT) + self._dct = dct + + def get_exact_index_types(self, index): + return list(chain.from_iterable(self._evaluator.eval_element(v) + for v in self._dct[index])) + + def _items(self): + return self._dct.items() + + class MergedArray(Array): def __init__(self, evaluator, arrays): super(MergedArray, self).__init__(evaluator, arrays[-1]._array) diff --git a/jedi/evaluate/param.py b/jedi/evaluate/param.py index 61fcfcba..47fc2668 100644 --- a/jedi/evaluate/param.py +++ b/jedi/evaluate/param.py @@ -1,4 +1,5 @@ import copy +from collections import defaultdict from jedi._compatibility import unicode, zip_longest from jedi import debug @@ -49,7 +50,7 @@ class Arguments(object): raise NotImplementedError else: if pr.is_node(el, 'argument'): - named_args.append((el.children[0], (el.children[2],))) + named_args.append((el.children[0].value, (el.children[2],))) else: yield None, (el,) @@ -57,7 +58,7 @@ class Arguments(object): # after named argument, but in the actual order it's prepended. for key_arg in named_args: # TODO its always only one value? - yield key_arg[0], (key_arg[1],) + yield key_arg def _reorder_var_args(var_args): named_index = None @@ -169,7 +170,7 @@ def get_params(evaluator, func, var_args): unpacked_va = var_args.unpack() var_arg_iterator = common.PushBackIterator(iter(unpacked_va)) - non_matching_keys = [] + non_matching_keys = defaultdict(lambda: []) keys_used = set() keys_only = False had_multiple_value_error = False @@ -185,7 +186,7 @@ def get_params(evaluator, func, var_args): try: key_param = param_dict[unicode(key)] except KeyError: - non_matching_keys.append((key, va_values)) + non_matching_keys[key] += va_values else: result.append(_gen_param_name_copy(evaluator, func, var_args, key_param, values=[va_values])) @@ -218,15 +219,13 @@ def get_params(evaluator, func, var_args): lst_values.append(va_values) if lst_values: values = [iterable.FakeSequence(evaluator, tuple(lst_values), - pr.Array.TUPLE)] + pr.Array.TUPLE)] #values = [helpers.stmts_to_stmt(v) for v in lst_values] elif param.stars == 2: # **kwargs param array_type = pr.Array.DICT - if non_matching_keys: - keys, values = zip(*non_matching_keys) - values = [helpers.stmts_to_stmt(list(v)) for v in values] - non_matching_keys = [] + values = [iterable.FakeDict(evaluator, dict(non_matching_keys))] + non_matching_keys = {} else: # normal param if va_values is not None: @@ -271,7 +270,7 @@ def get_params(evaluator, func, var_args): analysis.add(evaluator, 'type-error-too-few-arguments', calling_va, message=m) - for key, va_values in non_matching_keys: + for key, va_values in non_matching_keys.items(): m = "TypeError: %s() got an unexpected keyword argument '%s'." \ % (func.name, key) for value in va_values: diff --git a/jedi/parser/representation.py b/jedi/parser/representation.py index 5bfaa087..6aa4b22c 100644 --- a/jedi/parser/representation.py +++ b/jedi/parser/representation.py @@ -441,7 +441,7 @@ class Scope(Simple, DocstringMixin): :param start_pos: The position (line and column) of the scope. :type start_pos: tuple(int, int) """ - __slots__ = ('imports', '_doc_token', 'asserts', 'names_dict', + __slots__ = ('imports', '_doc_token', 'asserts', 'names_dict', 'is_generator') def __init__(self, children):