mirror of
https://github.com/davidhalter/jedi.git
synced 2025-12-15 10:07:06 +08:00
Add basic yield from type inference. References #647.
This commit is contained in:
@@ -677,12 +677,25 @@ class FunctionExecution(Executed):
|
|||||||
if check is flow_analysis.UNREACHABLE:
|
if check is flow_analysis.UNREACHABLE:
|
||||||
debug.dbg('Return unreachable: %s', r)
|
debug.dbg('Return unreachable: %s', r)
|
||||||
else:
|
else:
|
||||||
types |= self._evaluator.eval_element(r.children[1])
|
if check_yields:
|
||||||
|
types |= iterable.unite(self._eval_yield(r))
|
||||||
|
else:
|
||||||
|
types |= self._evaluator.eval_element(r.children[1])
|
||||||
if check is flow_analysis.REACHABLE:
|
if check is flow_analysis.REACHABLE:
|
||||||
debug.dbg('Return reachable: %s', r)
|
debug.dbg('Return reachable: %s', r)
|
||||||
break
|
break
|
||||||
return types
|
return types
|
||||||
|
|
||||||
|
def _eval_yield(self, yield_expr):
|
||||||
|
element = yield_expr.children[1]
|
||||||
|
if element.type == 'yield_arg':
|
||||||
|
# It must be a yield from.
|
||||||
|
yield_from_types = self._evaluator.eval_element(element.children[1])
|
||||||
|
for result in iterable.py__iter__(self._evaluator, yield_from_types, element):
|
||||||
|
yield result
|
||||||
|
else:
|
||||||
|
yield self._evaluator.eval_element(element)
|
||||||
|
|
||||||
# TODO add execution_recursion_decorator?!
|
# TODO add execution_recursion_decorator?!
|
||||||
def get_yield_types(self):
|
def get_yield_types(self):
|
||||||
yields = self.yields
|
yields = self.yields
|
||||||
@@ -716,7 +729,8 @@ class FunctionExecution(Executed):
|
|||||||
if for_stmt is None:
|
if for_stmt is None:
|
||||||
# No for_stmt, just normal yields.
|
# No for_stmt, just normal yields.
|
||||||
for yield_ in yields:
|
for yield_ in yields:
|
||||||
yield evaluator.eval_element(yield_.children[1])
|
for result in self._eval_yield(yield_):
|
||||||
|
yield result
|
||||||
else:
|
else:
|
||||||
input_node = for_stmt.get_input_node()
|
input_node = for_stmt.get_input_node()
|
||||||
for_types = evaluator.eval_element(input_node)
|
for_types = evaluator.eval_element(input_node)
|
||||||
@@ -725,7 +739,8 @@ class FunctionExecution(Executed):
|
|||||||
dct = {str(for_stmt.children[1]): index_types}
|
dct = {str(for_stmt.children[1]): index_types}
|
||||||
evaluator.predefined_if_name_dict_dict[for_stmt] = dct
|
evaluator.predefined_if_name_dict_dict[for_stmt] = dct
|
||||||
for yield_in_same_for_stmt in yields:
|
for yield_in_same_for_stmt in yields:
|
||||||
yield evaluator.eval_element(yield_in_same_for_stmt.children[1])
|
for result in self._eval_yield(yield_in_same_for_stmt):
|
||||||
|
yield result
|
||||||
del evaluator.predefined_if_name_dict_dict[for_stmt]
|
del evaluator.predefined_if_name_dict_dict[for_stmt]
|
||||||
|
|
||||||
def names_dicts(self, search_global):
|
def names_dicts(self, search_global):
|
||||||
|
|||||||
@@ -175,3 +175,25 @@ gen().send()
|
|||||||
|
|
||||||
#?
|
#?
|
||||||
gen()()
|
gen()()
|
||||||
|
|
||||||
|
# -----------------
|
||||||
|
# yield from
|
||||||
|
# -----------------
|
||||||
|
|
||||||
|
# python >= 3.3
|
||||||
|
|
||||||
|
def yield_from():
|
||||||
|
yield from iter([1])
|
||||||
|
|
||||||
|
#? int()
|
||||||
|
next(yield_from())
|
||||||
|
|
||||||
|
def yield_from_multiple():
|
||||||
|
yield from iter([1])
|
||||||
|
yield str()
|
||||||
|
|
||||||
|
x, y = yield_from_multiple()
|
||||||
|
#? int()
|
||||||
|
x
|
||||||
|
#? str()
|
||||||
|
y
|
||||||
|
|||||||
@@ -49,7 +49,7 @@ class Employee:
|
|||||||
|
|
||||||
# The typing library is not installable for Python 2.6, therefore ignore the
|
# The typing library is not installable for Python 2.6, therefore ignore the
|
||||||
# following tests.
|
# following tests.
|
||||||
# python > 2.6
|
# python >= 2.7
|
||||||
|
|
||||||
from typing import List
|
from typing import List
|
||||||
x = [] # type: List[Employee]
|
x = [] # type: List[Employee]
|
||||||
|
|||||||
@@ -240,8 +240,8 @@ def skip_python_version(line):
|
|||||||
'==': 'eq',
|
'==': 'eq',
|
||||||
'<=': 'le',
|
'<=': 'le',
|
||||||
'>=': 'ge',
|
'>=': 'ge',
|
||||||
'<': 'gk',
|
'<': 'lt',
|
||||||
'>': 'lt',
|
'>': 'gt',
|
||||||
}
|
}
|
||||||
# check for python minimal version number
|
# check for python minimal version number
|
||||||
match = re.match(r" *# *python *([<>]=?|==) *(\d+(?:\.\d+)?)$", line)
|
match = re.match(r" *# *python *([<>]=?|==) *(\d+(?:\.\d+)?)$", line)
|
||||||
|
|||||||
Reference in New Issue
Block a user