From 7848be97abd8a170253a81478b6f28b53ff8f34d Mon Sep 17 00:00:00 2001 From: Dave Halter Date: Sat, 12 Nov 2016 03:53:25 +0100 Subject: [PATCH] Some improvements towards iterators. --- jedi/evaluate/__init__.py | 5 ++--- jedi/evaluate/compiled/__init__.py | 4 ++-- jedi/evaluate/finder.py | 2 +- jedi/evaluate/instance.py | 35 +++++++++++++++--------------- jedi/evaluate/iterable.py | 6 +++-- 5 files changed, 27 insertions(+), 25 deletions(-) diff --git a/jedi/evaluate/__init__.py b/jedi/evaluate/__init__.py index a6aa6d34..52822509 100644 --- a/jedi/evaluate/__init__.py +++ b/jedi/evaluate/__init__.py @@ -152,8 +152,7 @@ class Evaluator(object): operator = copy.copy(first_operation) operator.value = operator.value[:-1] name = str(stmt.get_defined_names()[0]) - parent = self.wrap(stmt.get_parent_scope()) - left = self.find_types(parent, name, stmt.start_pos, search_global=True) + left = self.find_types(context, name, stmt.start_pos, search_global=True) for_stmt = stmt.get_parent_until(tree.ForStmt) if isinstance(for_stmt, tree.ForStmt) and types \ @@ -351,7 +350,7 @@ class Evaluator(object): elif c[0] == '(' and not len(c) == 2 \ and not(tree.is_node(c[1], 'testlist_comp') and len(c[1].children) > 1): - return self.eval_element(c[1]) + return self.eval_element(context, c[1]) try: comp_for = c[1].children[1] diff --git a/jedi/evaluate/compiled/__init__.py b/jedi/evaluate/compiled/__init__.py index 6b39e599..e0d9273b 100644 --- a/jedi/evaluate/compiled/__init__.py +++ b/jedi/evaluate/compiled/__init__.py @@ -13,7 +13,7 @@ from jedi.cache import underscore_memoization, memoize_method from jedi.parser.tree import Param, Operator from jedi.evaluate.helpers import FakeName from jedi.evaluate.filters import AbstractFilter, AbstractNameDefinition -from jedi.evaluate.context import Context +from jedi.evaluate.context import Context, LazyKnownContext from . import fake @@ -202,7 +202,7 @@ class CompiledObject(Context): return for part in self.obj: - yield set([create(self.evaluator, part)]) + yield LazyKnownContext(create(self.evaluator, part)) @property def name(self): diff --git a/jedi/evaluate/finder.py b/jedi/evaluate/finder.py index 1ccfe768..3ce8b6e3 100644 --- a/jedi/evaluate/finder.py +++ b/jedi/evaluate/finder.py @@ -370,7 +370,7 @@ def _name_to_types(evaluator, context, name, scope): elif node.isinstance(tree.ExprStmt): types = _remove_statements(evaluator, context, node, name) elif node.isinstance(tree.WithStmt): - types = evaluator.eval_element(node.node_from_name(name)) + types = context.eval_node(node.node_from_name(name)) elif isinstance(node, tree.Import): types = imports.ImportWrapper(context, name).follow() elif node.type in ('funcdef', 'classdef'): diff --git a/jedi/evaluate/instance.py b/jedi/evaluate/instance.py index 2464c6e6..2584026c 100644 --- a/jedi/evaluate/instance.py +++ b/jedi/evaluate/instance.py @@ -1,10 +1,11 @@ from abc import abstractproperty +from jedi._compatibility import is_py3 from jedi.common import unite from jedi import debug from jedi.evaluate import compiled from jedi.evaluate import filters -from jedi.evaluate.context import Context, LazyKnownContext +from jedi.evaluate.context import Context, LazyKnownContext, get_merged_lazy_context from jedi.evaluate.cache import memoize_default from jedi.cache import memoize_method from jedi.evaluate import representation as er @@ -117,24 +118,24 @@ class AbstractInstanceContext(Context): return unite(name.execute_evaluated(index_obj) for name in names) def py__iter__(self): - try: - method = self.get_subscope_by_name('__iter__') - except KeyError: + iter_slot_names = self.get_function_slot_names('__iter__') + if not iter_slot_names: debug.warning('No __iter__ on %s.' % self) return - else: - iters = self.evaluator.execute(method) - for generator in iters: - if isinstance(generator, Instance): - # `__next__` logic. - name = '__next__' if is_py3 else 'next' - try: - yield generator.execute_subscope_by_name(name) - except KeyError: - debug.warning('Instance has no __next__ function in %s.', generator) - else: - for typ in generator.py__iter__(): - yield typ + + for generator in self.execute_function_slots(iter_slot_names): + if isinstance(generator, AbstractInstanceContext): + # `__next__` logic. + name = '__next__' if is_py3 else 'next' + try: + yield get_merged_lazy_context( + generator.execute_subscope_by_name(name) + ) + except KeyError: + debug.warning('Instance has no __next__ function in %s.', generator) + else: + for lazy_context in generator.py__iter__(): + yield lazy_context @abstractproperty def name(self): diff --git a/jedi/evaluate/iterable.py b/jedi/evaluate/iterable.py index aa58887c..09806360 100644 --- a/jedi/evaluate/iterable.py +++ b/jedi/evaluate/iterable.py @@ -611,8 +611,10 @@ def py__iter__(evaluator, types, node=None): else: type_iters.append(iter_method()) - for lazy_contexts in zip_longest(*type_iters, fillvalue=set()): - yield context.get_merged_lazy_context(lazy_contexts) + for lazy_contexts in zip_longest(*type_iters, fillvalue=None): + yield context.get_merged_lazy_context( + [l for l in lazy_contexts if l is not None] + ) def py__iter__types(evaluator, types, node=None):