def get_return_values(self, check_yields=False): funcdef = self.tree_node if funcdef.type == 'lambdef': return self.eval_node(funcdef.children[-1]) if check_yields: context_set = NO_CONTEXTS returns = get_yield_exprs(self.evaluator, funcdef) else: returns = funcdef.iter_return_stmts() context_set = docstrings.infer_return_types(self.function_context) context_set |= pep0484.infer_return_types(self.function_context) for r in returns: check = flow_analysis.reachability_check(self, funcdef, r) if check is flow_analysis.UNREACHABLE: debug.dbg('Return unreachable: %s', r) else: if check_yields: context_set |= ContextSet.from_sets( lazy_context.infer() for lazy_context in self._get_yield_lazy_context(r) ) else: try: children = r.children except AttributeError: ctx = compiled.builtin_from_name(self.evaluator, u'None') context_set |= ContextSet(ctx) else: context_set |= self.eval_node(children[1]) if check is flow_analysis.REACHABLE: debug.dbg('Return reachable: %s', r) break return context_set
def infer_function_execution(self, function_execution): """ Created to be used by inheritance. """ is_coroutine = self.tree_node.parent.type == 'async_stmt' is_generator = bool(get_yield_exprs(self.evaluator, self.tree_node)) if is_coroutine: if is_generator: if self.evaluator.environment.version_info < (3, 6): return NO_CONTEXTS return ContextSet( asynchronous.AsyncGenerator(self.evaluator, function_execution)) else: if self.evaluator.environment.version_info < (3, 5): return NO_CONTEXTS return ContextSet( asynchronous.Coroutine(self.evaluator, function_execution)) else: if is_generator: return ContextSet( iterable.Generator(self.evaluator, function_execution)) else: return function_execution.get_return_values()
def get_return_values(self, check_yields=False): funcdef = self.tree_node if funcdef.type == 'lambdef': return self.evaluator.eval_element(self, funcdef.children[-1]) if check_yields: types = set() returns = get_yield_exprs(self.evaluator, funcdef) else: returns = funcdef.iter_return_stmts() types = set(docstrings.infer_return_types(self.function_context)) types |= set(pep0484.infer_return_types(self.function_context)) for r in returns: check = flow_analysis.reachability_check(self, funcdef, r) if check is flow_analysis.UNREACHABLE: debug.dbg('Return unreachable: %s', r) else: if check_yields: types |= set(self._eval_yield(r)) else: try: children = r.children except AttributeError: types.add(compiled.create(self.evaluator, None)) else: types |= self.eval_node(children[1]) if check is flow_analysis.REACHABLE: debug.dbg('Return reachable: %s', r) break return types
def infer_function_execution(self, function_execution): """ Created to be used by inheritance. """ yield_exprs = get_yield_exprs(self.evaluator, self.tree_node) if yield_exprs: return set([iterable.Generator(self.evaluator, function_execution)]) else: return function_execution.get_return_values()
def infer_function_execution(self, function_execution): """ Created to be used by inheritance. """ yield_exprs = get_yield_exprs(self.evaluator, self.tree_node) if yield_exprs: return set( [iterable.Generator(self.evaluator, function_execution)]) else: return function_execution.get_return_values()
def get_yield_lazy_contexts(self, is_async=False): # TODO: if is_async, wrap yield statements in Awaitable/async_generator_asend for_parents = [(y, tree.search_ancestor(y, 'for_stmt', 'funcdef', 'while_stmt', 'if_stmt')) for y in get_yield_exprs(self.evaluator, self.tree_node) ] # 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.tree_node \ and parser_utils.for_stmt_defines_one_name(for_stmt): # Simplicity for now. if for_stmt == last_for_stmt: yields_order[-1][1].append(yield_) else: yields_order.append((for_stmt, [yield_])) elif for_stmt == self.tree_node: yields_order.append((None, [yield_])) else: types = self.get_return_values(check_yields=True) if types: yield LazyKnownContexts(types) return last_for_stmt = for_stmt for for_stmt, yields in yields_order: if for_stmt is None: # No for_stmt, just normal yields. for yield_ in yields: for result in self._get_yield_lazy_context(yield_): yield result else: input_node = for_stmt.get_testlist() cn = ContextualizedNode(self, input_node) ordered = cn.infer().iterate(cn) ordered = list(ordered) for lazy_context in ordered: dct = { str(for_stmt.children[1].value): lazy_context.infer() } with helpers.predefine_names(self, for_stmt, dct): for yield_in_same_for_stmt in yields: for result in self._get_yield_lazy_context( yield_in_same_for_stmt): yield result
def get_yield_lazy_contexts(self, is_async=False): # TODO: if is_async, wrap yield statements in Awaitable/async_generator_asend for_parents = [(y, tree.search_ancestor(y, 'for_stmt', 'funcdef', 'while_stmt', 'if_stmt')) for y in get_yield_exprs(self.evaluator, self.tree_node)] # 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.tree_node \ and parser_utils.for_stmt_defines_one_name(for_stmt): # Simplicity for now. if for_stmt == last_for_stmt: yields_order[-1][1].append(yield_) else: yields_order.append((for_stmt, [yield_])) elif for_stmt == self.tree_node: yields_order.append((None, [yield_])) else: types = self.get_return_values(check_yields=True) if types: yield LazyKnownContexts(types) return last_for_stmt = for_stmt for for_stmt, yields in yields_order: if for_stmt is None: # No for_stmt, just normal yields. for yield_ in yields: for result in self._get_yield_lazy_context(yield_): yield result else: input_node = for_stmt.get_testlist() cn = ContextualizedNode(self, input_node) ordered = cn.infer().iterate(cn) ordered = list(ordered) for lazy_context in ordered: dct = {str(for_stmt.children[1].value): lazy_context.infer()} with helpers.predefine_names(self, for_stmt, dct): for yield_in_same_for_stmt in yields: for result in self._get_yield_lazy_context(yield_in_same_for_stmt): yield result
def infer(self): """ Created to be used by inheritance. """ evaluator = self.evaluator is_coroutine = self.tree_node.parent.type in ('async_stmt', 'async_funcdef') is_generator = bool(get_yield_exprs(evaluator, self.tree_node)) from jedi.evaluate.gradual.typing import GenericClass if is_coroutine: if is_generator: if evaluator.environment.version_info < (3, 6): return NO_CONTEXTS async_generator_classes = evaluator.typing_module \ .py__getattribute__('AsyncGenerator') yield_contexts = self.merge_yield_contexts(is_async=True) # The contravariant doesn't seem to be defined. generics = (yield_contexts.py__class__(), NO_CONTEXTS) return ContextSet( # In Python 3.6 AsyncGenerator is still a class. GenericClass(c, generics) for c in async_generator_classes).execute_annotation() else: if evaluator.environment.version_info < (3, 5): return NO_CONTEXTS async_classes = evaluator.typing_module.py__getattribute__( 'Coroutine') return_contexts = self.get_return_values() # Only the first generic is relevant. generics = (return_contexts.py__class__(), NO_CONTEXTS, NO_CONTEXTS) return ContextSet( GenericClass(c, generics) for c in async_classes).execute_annotation() else: if is_generator: return ContextSet([iterable.Generator(evaluator, self)]) else: return self.get_return_values()
def infer_function_execution(self, function_execution): """ Created to be used by inheritance. """ is_coroutine = self.tree_node.parent.type == 'async_stmt' is_generator = bool(get_yield_exprs(self.evaluator, self.tree_node)) if is_coroutine: if is_generator: if self.evaluator.environment.version_info < (3, 6): return NO_CONTEXTS return ContextSet(asynchronous.AsyncGenerator(self.evaluator, function_execution)) else: if self.evaluator.environment.version_info < (3, 5): return NO_CONTEXTS return ContextSet(asynchronous.Coroutine(self.evaluator, function_execution)) else: if is_generator: return ContextSet(iterable.Generator(self.evaluator, function_execution)) else: return function_execution.get_return_values()
def get_return_values(self, check_yields=False): funcdef = self.tree_node if funcdef.type == 'lambdef': return self.eval_node(funcdef.children[-1]) if check_yields: context_set = NO_CONTEXTS returns = get_yield_exprs(self.evaluator, funcdef) else: returns = funcdef.iter_return_stmts() from jedi.evaluate.gradual.annotation import infer_return_types context_set = infer_return_types(self) if context_set: # If there are annotations, prefer them over anything else. # This will make it faster. return context_set context_set |= docstrings.infer_return_types(self.function_context) for r in returns: check = flow_analysis.reachability_check(self, funcdef, r) if check is flow_analysis.UNREACHABLE: debug.dbg('Return unreachable: %s', r) else: if check_yields: context_set |= ContextSet.from_sets( lazy_context.infer() for lazy_context in self._get_yield_lazy_context(r)) else: try: children = r.children except AttributeError: ctx = compiled.builtin_from_name( self.evaluator, u'None') context_set |= ContextSet([ctx]) else: context_set |= self.eval_node(children[1]) if check is flow_analysis.REACHABLE: debug.dbg('Return reachable: %s', r) break return context_set