forked from VimPlug/jedi
Implement py__iter__ for Generators, which means that yield expressions are now orderable, if they are not too complicated.
This commit is contained in:
@@ -86,6 +86,11 @@ class Generator(use_metaclass(CachedMetaClass, IterableWrapper, GeneratorMixin))
|
|||||||
f = FunctionExecution(self._evaluator, self.func, self.var_args)
|
f = FunctionExecution(self._evaluator, self.func, self.var_args)
|
||||||
return f.get_return_types(check_yields=True)
|
return f.get_return_types(check_yields=True)
|
||||||
|
|
||||||
|
def py__iter__(self):
|
||||||
|
from jedi.evaluate.representation import FunctionExecution
|
||||||
|
f = FunctionExecution(self._evaluator, self.func, self.var_args)
|
||||||
|
return f.get_yield_types()
|
||||||
|
|
||||||
def __getattr__(self, name):
|
def __getattr__(self, name):
|
||||||
if name not in ['start_pos', 'end_pos', 'parent', 'get_imports',
|
if name not in ['start_pos', 'end_pos', 'parent', 'get_imports',
|
||||||
'doc', 'docstr', 'get_parent_until',
|
'doc', 'docstr', 'get_parent_until',
|
||||||
@@ -274,7 +279,7 @@ class Array(IterableWrapper, ArrayMixin):
|
|||||||
raise AttributeError('Strange access on %s: %s.' % (self, name))
|
raise AttributeError('Strange access on %s: %s.' % (self, name))
|
||||||
return getattr(self.atom, name)
|
return getattr(self.atom, name)
|
||||||
|
|
||||||
def per_index_values(self):
|
def py__iter__(self):
|
||||||
"""
|
"""
|
||||||
While values returns the possible values for any array field, this
|
While values returns the possible values for any array field, this
|
||||||
function returns the value for a certain index.
|
function returns the value for a certain index.
|
||||||
@@ -401,12 +406,13 @@ def ordered_elements_of_iterable(evaluator, iterable_type, all_values):
|
|||||||
# Unpack the iterator values
|
# Unpack the iterator values
|
||||||
for sequence in iterable_type:
|
for sequence in iterable_type:
|
||||||
try:
|
try:
|
||||||
per_index_values = sequence.per_index_values
|
# TODO every type should have a py__iter__ method.
|
||||||
|
py__iter__ = sequence.py__iter__
|
||||||
except AttributeError:
|
except AttributeError:
|
||||||
ordered = [literals_to_types(evaluator, all_values)]
|
ordered = [literals_to_types(evaluator, all_values)]
|
||||||
break
|
break
|
||||||
else:
|
else:
|
||||||
for i, types in enumerate(per_index_values()):
|
for i, types in enumerate(py__iter__()):
|
||||||
try:
|
try:
|
||||||
ordered[i] |= types
|
ordered[i] |= types
|
||||||
except IndexError:
|
except IndexError:
|
||||||
|
|||||||
@@ -211,6 +211,17 @@ class Instance(use_metaclass(CachedMetaClass, Executed)):
|
|||||||
else:
|
else:
|
||||||
return self._evaluator.execute(method, [iterable.AlreadyEvaluated(indexes)])
|
return self._evaluator.execute(method, [iterable.AlreadyEvaluated(indexes)])
|
||||||
|
|
||||||
|
def py__iter__(self):
|
||||||
|
try:
|
||||||
|
method = self.get_subscope_by_name('__iter__')
|
||||||
|
except KeyError:
|
||||||
|
debug.warning('No __iter__ on %s.' % self)
|
||||||
|
return
|
||||||
|
else:
|
||||||
|
for generator in self._evaluator.execute(method):
|
||||||
|
for typ in generator.py__iter__():
|
||||||
|
yield typ
|
||||||
|
|
||||||
@property
|
@property
|
||||||
@underscore_memoization
|
@underscore_memoization
|
||||||
def name(self):
|
def name(self):
|
||||||
@@ -228,7 +239,7 @@ class Instance(use_metaclass(CachedMetaClass, Executed)):
|
|||||||
dec = ''
|
dec = ''
|
||||||
if self.decorates is not None:
|
if self.decorates is not None:
|
||||||
dec = " decorates " + repr(self.decorates)
|
dec = " decorates " + repr(self.decorates)
|
||||||
return "<e%s of %s(%s)%s>" % (type(self).__name__, self.base,
|
return "<%s of %s(%s)%s>" % (type(self).__name__, self.base,
|
||||||
self.var_args, dec)
|
self.var_args, dec)
|
||||||
|
|
||||||
|
|
||||||
@@ -633,6 +644,41 @@ class FunctionExecution(Executed):
|
|||||||
break
|
break
|
||||||
return types
|
return types
|
||||||
|
|
||||||
|
def get_yield_types(self):
|
||||||
|
yields = self.yields
|
||||||
|
stopAt = tree.ForStmt, tree.WhileStmt, FunctionExecution
|
||||||
|
for_parents = [(x, x.get_parent_until((stopAt))) for x in yields]
|
||||||
|
|
||||||
|
# Calculate if the yields are placed within the same for loop.
|
||||||
|
yields_order = []
|
||||||
|
last_for_stmt = None
|
||||||
|
for yield_, for_stmt in for_parents:
|
||||||
|
# For really simple for loops we can predict the order. Otherwise
|
||||||
|
# we just ignore it.
|
||||||
|
parent = for_stmt.parent
|
||||||
|
if parent.type == 'suite':
|
||||||
|
parent = parent.parent
|
||||||
|
if for_stmt.type == 'for_stmt' and parent == self \
|
||||||
|
and for_stmt.defines_one_name(): # Simplicity for now.
|
||||||
|
if for_stmt == last_for_stmt:
|
||||||
|
yields_order[-1][1].append(yield_)
|
||||||
|
else:
|
||||||
|
yields_order.append((for_stmt, [yield_]))
|
||||||
|
else:
|
||||||
|
yield self.get_return_types()
|
||||||
|
return
|
||||||
|
last_for_stmt = for_stmt
|
||||||
|
|
||||||
|
for for_stmt, yields in yields_order:
|
||||||
|
for_types = self._evaluator.eval_element(for_stmt.get_input_node())
|
||||||
|
ordered = iterable.ordered_elements_of_iterable(self._evaluator, for_types, [])
|
||||||
|
for index_types in ordered:
|
||||||
|
dct = {str(for_stmt.children[1]): index_types}
|
||||||
|
self._evaluator.predefined_if_name_dict_dict[for_stmt] = dct
|
||||||
|
for yield_in_same_for_stmt in yields:
|
||||||
|
yield self._evaluator.eval_element(yield_in_same_for_stmt.children[1])
|
||||||
|
del self._evaluator.predefined_if_name_dict_dict[for_stmt]
|
||||||
|
|
||||||
def names_dicts(self, search_global):
|
def names_dicts(self, search_global):
|
||||||
yield self.names_dict
|
yield self.names_dict
|
||||||
|
|
||||||
|
|||||||
@@ -483,7 +483,7 @@ class BaseNode(Base):
|
|||||||
|
|
||||||
@utf8_repr
|
@utf8_repr
|
||||||
def __repr__(self):
|
def __repr__(self):
|
||||||
code = self.get_code().replace('\n', ' ')
|
code = self.get_code().replace('\n', ' ').strip()
|
||||||
if not is_py3:
|
if not is_py3:
|
||||||
code = code.encode(encoding, 'replace')
|
code = code.encode(encoding, 'replace')
|
||||||
return "<%s: %s@%s,%s>" % \
|
return "<%s: %s@%s,%s>" % \
|
||||||
|
|||||||
Reference in New Issue
Block a user