diff --git a/jedi/evaluate/__init__.py b/jedi/evaluate/__init__.py index 0381c04d..f858e136 100644 --- a/jedi/evaluate/__init__.py +++ b/jedi/evaluate/__init__.py @@ -275,8 +275,11 @@ class Evaluator(object): # This must be an execution, either () or []. if current.type == pr.Array.LIST: if hasattr(typ, 'get_index_types'): - slc = iterable.create_indexes_or_slices(self, current) - result = typ.get_index_types(slc) + if isinstance(typ, compiled.CompiledObject): + # CompiledObject doesn't contain an evaluator instance. + result = typ.get_index_types(self, current) + else: + result = typ.get_index_types(current) elif current.type not in [pr.Array.DICT]: # Scope must be a class or func - make an instance or execution. result = self.execute(typ, current) diff --git a/jedi/evaluate/compiled/__init__.py b/jedi/evaluate/compiled/__init__.py index df82cbb8..4d4c106a 100644 --- a/jedi/evaluate/compiled/__init__.py +++ b/jedi/evaluate/compiled/__init__.py @@ -99,7 +99,7 @@ class CompiledObject(Base): else: raise KeyError("CompiledObject doesn't have an attribute '%s'." % name) - def get_index_types(self, index_types): + def get_index_types(self, evaluator, index_array): # If the object doesn't have `__getitem__`, just raise the # AttributeError. if not hasattr(self.obj, '__getitem__'): @@ -110,7 +110,8 @@ class CompiledObject(Base): return [] result = [] - for typ in index_types: + from jedi.evaluate.iterable import create_indexes_or_slices + for typ in create_indexes_or_slices(evaluator, index_array): index = None try: index = typ.obj diff --git a/jedi/evaluate/finder.py b/jedi/evaluate/finder.py index 4182dc21..f7c6683e 100644 --- a/jedi/evaluate/finder.py +++ b/jedi/evaluate/finder.py @@ -356,7 +356,7 @@ def _check_isinstance_type(evaluator, stmt, search_name_part): result = [] for c in evaluator.eval_call(classes[0]): - for typ in (c.get_index_types() if isinstance(c, iterable.Array) else [c]): + for typ in (c.values() if isinstance(c, iterable.Array) else [c]): result += evaluator.execute(typ) return result diff --git a/jedi/evaluate/iterable.py b/jedi/evaluate/iterable.py index 1742c133..9ff78e65 100644 --- a/jedi/evaluate/iterable.py +++ b/jedi/evaluate/iterable.py @@ -60,7 +60,7 @@ class Generator(use_metaclass(CachedMetaClass, pr.Base)): """ returns the content of __iter__ """ return self._evaluator.execute(self.func, self.var_args, True) - def get_index_types(self, index=None): + def get_index_types(self, index_array): debug.warning('Tried to get array access on a generator: %s', self) return [] @@ -99,13 +99,13 @@ class Array(use_metaclass(CachedMetaClass, pr.Base)): self._array = array @memoize_default(NO_DEFAULT) - def get_index_types(self, indexes=()): + def get_index_types(self, index_array=()): """ Get the types of a specific index or all, if not given. :param indexes: The index input types. """ - result = [] + indexes = create_indexes_or_slices(self._evaluator, index_array) if [index for index in indexes if isinstance(index, Slice)]: return [self] @@ -118,6 +118,10 @@ class Array(use_metaclass(CachedMetaClass, pr.Base)): with common.ignored(KeyError, IndexError, TypeError): return self.get_exact_index_types(index.obj) + return self.values() + + @memoize_default(NO_DEFAULT) + def values(self): result = list(_follow_values(self._evaluator, self._array.values)) result += check_array_additions(self._evaluator, self) return result @@ -228,22 +232,22 @@ def get_iterator_types(inputs): result = [] from jedi.evaluate.representation import Instance - for gen in iterators: - if isinstance(gen, Array): + for it in iterators: + if isinstance(it, Array): # Array is a little bit special, since this is an internal # array, but there's also the list builtin, which is # another thing. - result += gen.get_index_types() - elif isinstance(gen, Instance): + result += it.values() + elif isinstance(it, Instance): # __iter__ returned an instance. name = '__next__' if is_py3 else 'next' try: - result += gen.execute_subscope_by_name(name) + result += it.execute_subscope_by_name(name) except KeyError: - debug.warning('Instance has no __next__ function in %s.', gen) + debug.warning('Instance has no __next__ function in %s.', it) else: - # is a generator - result += gen.iter_content() + # Is a generator. + result += it.iter_content() return result diff --git a/jedi/evaluate/representation.py b/jedi/evaluate/representation.py index e367c10a..c9b886d4 100644 --- a/jedi/evaluate/representation.py +++ b/jedi/evaluate/representation.py @@ -168,7 +168,9 @@ class Instance(use_metaclass(CachedMetaClass, Executable)): except KeyError: return False - def get_index_types(self, indexes=[]): + def get_index_types(self, index_array): + + indexes = iterable.create_indexes_or_slices(self._evaluator, index_array) if any([isinstance(i, iterable.Slice) for i in indexes]): # Slice support in Jedi is very marginal, at the moment, so just # ignore them in case of __getitem__. diff --git a/test/static_analysis/attribute_error.py b/test/static_analysis/attribute_error.py index a5a243e1..ac83b792 100644 --- a/test/static_analysis/attribute_error.py +++ b/test/static_analysis/attribute_error.py @@ -17,8 +17,7 @@ class Cls(): def defined_lookup(self, obj): """ - Uses an arbitrary object and performs an operation on it, shouldn't - be a problem. + `obj` is defined by a call into this function. """ obj.upper #! attribute-error