def from_scope_node(scope_node, child_is_funcdef=None, is_nested=True, node_is_object=False): if scope_node == base_node: return base_context is_funcdef = scope_node.type in ('funcdef', 'lambdef') parent_scope = parser_utils.get_parent_scope(scope_node) parent_context = from_scope_node(parent_scope, child_is_funcdef=is_funcdef) if is_funcdef: if isinstance(parent_context, AnonymousInstance): func = BoundMethod( self, parent_context, parent_context.class_context, parent_context.parent_context, scope_node ) else: func = FunctionContext( self, parent_context, scope_node ) if is_nested and not node_is_object: return func.get_function_execution() return func elif scope_node.type == 'classdef': class_context = ClassContext(self, parent_context, scope_node) if child_is_funcdef: # anonymous instance return AnonymousInstance(self, parent_context, class_context) else: return class_context elif scope_node.type == 'comp_for': if node.start_pos >= scope_node.children[-1].start_pos: return parent_context return CompForContext.from_comp_for(parent_context, scope_node) raise Exception("There's a scope that was not managed.")
def create_instance_context(self, class_context, node): if node.parent.type in ('funcdef', 'classdef'): node = node.parent scope = get_parent_scope(node) if scope == class_context.tree_node: return class_context else: parent_context = self.create_instance_context(class_context, scope) if scope.type == 'funcdef': func = FunctionContext.from_context( parent_context, scope, ) bound_method = BoundMethod(self, func) if scope.name.value == '__init__' and parent_context == class_context: return bound_method.get_function_execution(self.var_args) else: return bound_method.get_function_execution() elif scope.type == 'classdef': class_context = ClassContext(self.evaluator, parent_context, scope) return class_context elif scope.type == 'comp_for': # Comprehensions currently don't have a special scope in Jedi. return self.create_instance_context(class_context, scope) else: raise NotImplementedError return class_context
def from_scope_node(scope_node, child_is_funcdef=None, is_nested=True, node_is_object=False): if scope_node == base_node: return base_context is_funcdef = scope_node.type in ('funcdef', 'lambdef') parent_scope = parser_utils.get_parent_scope(scope_node) parent_context = from_scope_node(parent_scope, child_is_funcdef=is_funcdef) if is_funcdef: if isinstance(parent_context, AnonymousInstance): func = BoundMethod( self, parent_context, parent_context.class_context, parent_context.parent_context, scope_node ) else: func = er.FunctionContext( self, parent_context, scope_node ) if is_nested and not node_is_object: return func.get_function_execution() return func elif scope_node.type == 'classdef': class_context = er.ClassContext(self, scope_node, parent_context) if child_is_funcdef: # anonymous instance return AnonymousInstance(self, parent_context, class_context) else: return class_context elif scope_node.type == 'comp_for': if node.start_pos >= scope_node.children[-1].start_pos: return parent_context return iterable.CompForContext.from_comp_for(parent_context, scope_node) raise Exception("There's a scope that was not managed.")
def _names_to_types(self, names, attribute_lookup): types = set() types = unite(name.infer() for name in names) debug.dbg('finder._names_to_types: %s -> %s', names, types) if not names and isinstance(self._context, AbstractInstanceContext): # handling __getattr__ / __getattribute__ return self._check_getattr(self._context) # Add isinstance and other if/assert knowledge. if not types and isinstance(self._name, tree.Name) and \ not isinstance(self._name_context, AbstractInstanceContext): flow_scope = self._name base_node = self._name_context.tree_node if base_node.type == 'comp_for': return types while True: flow_scope = get_parent_scope(flow_scope, include_flows=True) n = _check_flow_information(self._name_context, flow_scope, self._name, self._position) if n is not None: return n if flow_scope == base_node: break return types
def _equals_origin_scope(self): node = self._origin_scope while node is not None: if node == self._parser_scope or node == self.context: return True node = get_parent_scope(node) return False
def _break_check(context, value_scope, flow_scope, node): reachable = REACHABLE if flow_scope.type == 'if_stmt': if flow_scope.is_node_after_else(node): for check_node in flow_scope.get_test_nodes(): reachable = _check_if(context, check_node) if reachable in (REACHABLE, UNSURE): break reachable = reachable.invert() else: flow_node = flow_scope.get_corresponding_test_node(node) if flow_node is not None: reachable = _check_if(context, flow_node) elif flow_scope.type in ('try_stmt', 'while_stmt'): return UNSURE # Only reachable branches need to be examined further. if reachable in (UNREACHABLE, UNSURE): return reachable if value_scope != flow_scope and value_scope != flow_scope.parent: flow_scope = get_parent_scope(flow_scope, include_flows=True) return reachable & _break_check(context, value_scope, flow_scope, node) else: return reachable
def _names_to_types(self, names, attribute_lookup): contexts = ContextSet.from_sets(name.infer() for name in names) debug.dbg('finder._names_to_types: %s -> %s', names, contexts) if not names and self._context.is_instance( ) and not self._context.is_compiled(): # handling __getattr__ / __getattribute__ return self._check_getattr(self._context) # Add isinstance and other if/assert knowledge. if not contexts and isinstance(self._name, tree.Name) and \ not self._name_context.is_instance() and not self._context.is_compiled(): flow_scope = self._name base_nodes = [self._name_context.tree_node] if any(b.type in ('comp_for', 'sync_comp_for') for b in base_nodes): return contexts while True: flow_scope = get_parent_scope(flow_scope, include_flows=True) n = _check_flow_information(self._name_context, flow_scope, self._name, self._position) if n is not None: return n if flow_scope in base_nodes: break return contexts
def _break_check(context, context_scope, flow_scope, node): reachable = REACHABLE if flow_scope.type == 'if_stmt': if flow_scope.is_node_after_else(node): for check_node in flow_scope.get_test_nodes(): reachable = _check_if(context, check_node) if reachable in (REACHABLE, UNSURE): break reachable = reachable.invert() else: flow_node = flow_scope.get_corresponding_test_node(node) if flow_node is not None: reachable = _check_if(context, flow_node) elif flow_scope.type in ('try_stmt', 'while_stmt'): return UNSURE # Only reachable branches need to be examined further. if reachable in (UNREACHABLE, UNSURE): return reachable if context_scope != flow_scope and context_scope != flow_scope.parent: flow_scope = get_parent_scope(flow_scope, include_flows=True) return reachable & _break_check(context, context_scope, flow_scope, node) else: return reachable
def reachability_check(context, context_scope, node, origin_scope=None): first_flow_scope = get_parent_scope(node, include_flows=True) if origin_scope is not None: origin_flow_scopes = list(_get_flow_scopes(origin_scope)) node_flow_scopes = list(_get_flow_scopes(node)) branch_matches = True for flow_scope in origin_flow_scopes: if flow_scope in node_flow_scopes: node_keyword = get_flow_branch_keyword(flow_scope, node) origin_keyword = get_flow_branch_keyword( flow_scope, origin_scope) branch_matches = node_keyword == origin_keyword if flow_scope.type == 'if_stmt': if not branch_matches: return UNREACHABLE elif flow_scope.type == 'try_stmt': if not branch_matches and origin_keyword == 'else' \ and node_keyword == 'except': return UNREACHABLE break # Direct parents get resolved, we filter scopes that are separate # branches. This makes sense for autocompletion and static analysis. # For actual Python it doesn't matter, because we're talking about # potentially unreachable code. # e.g. `if 0:` would cause all name lookup within the flow make # unaccessible. This is not a "problem" in Python, because the code is # never called. In Jedi though, we still want to infer types. while origin_scope is not None: if first_flow_scope == origin_scope and branch_matches: return REACHABLE origin_scope = origin_scope.parent return _break_check(context, context_scope, first_flow_scope, node)
def reachability_check(context, context_scope, node, origin_scope=None): first_flow_scope = get_parent_scope(node, include_flows=True) if origin_scope is not None: origin_flow_scopes = list(_get_flow_scopes(origin_scope)) node_flow_scopes = list(_get_flow_scopes(node)) branch_matches = True for flow_scope in origin_flow_scopes: if flow_scope in node_flow_scopes: node_keyword = get_flow_branch_keyword(flow_scope, node) origin_keyword = get_flow_branch_keyword(flow_scope, origin_scope) branch_matches = node_keyword == origin_keyword if flow_scope.type == 'if_stmt': if not branch_matches: return UNREACHABLE elif flow_scope.type == 'try_stmt': if not branch_matches and origin_keyword == 'else' \ and node_keyword == 'except': return UNREACHABLE if branch_matches: break # Direct parents get resolved, we filter scopes that are separate # branches. This makes sense for autocompletion and static analysis. # For actual Python it doesn't matter, because we're talking about # potentially unreachable code. # e.g. `if 0:` would cause all name lookup within the flow make # unaccessible. This is not a "problem" in Python, because the code is # never called. In Jedi though, we still want to infer types. while origin_scope is not None: if first_flow_scope == origin_scope and branch_matches: return REACHABLE origin_scope = origin_scope.parent return _break_check(context, context_scope, first_flow_scope, node)
def from_scope_node(scope_node, is_nested=True, node_is_object=False): if scope_node == base_node: return base_context is_funcdef = scope_node.type in ('funcdef', 'lambdef') parent_scope = parser_utils.get_parent_scope(scope_node) parent_context = from_scope_node(parent_scope) if is_funcdef: func = FunctionContext.from_context(parent_context, scope_node) if parent_context.is_class(): instance = AnonymousInstance( self, parent_context.parent_context, parent_context) func = BoundMethod( instance=instance, function=func ) if is_nested and not node_is_object: return func.get_function_execution() return func elif scope_node.type == 'classdef': return ClassContext(self, parent_context, scope_node) elif scope_node.type == 'comp_for': if node.start_pos >= scope_node.children[-1].start_pos: return parent_context return CompForContext.from_comp_for(parent_context, scope_node) raise Exception("There's a scope that was not managed.")
def create_instance_context(self, class_context, node): if node.parent.type in ('funcdef', 'classdef'): node = node.parent scope = get_parent_scope(node) if scope == class_context.tree_node: return class_context else: parent_context = self.create_instance_context(class_context, scope) if scope.type == 'funcdef': if scope.name.value == '__init__' and parent_context == class_context: return self._create_init_execution(class_context, scope) else: bound_method = BoundMethod( self.evaluator, self, class_context, parent_context, scope ) return bound_method.get_function_execution() elif scope.type == 'classdef': class_context = ClassContext(self.evaluator, scope, parent_context) return class_context elif scope.type == 'comp_for': # Comprehensions currently don't have a special scope in Jedi. return self.create_instance_context(class_context, scope) else: raise NotImplementedError return class_context
def _names_to_types(self, names, attribute_lookup): types = set() types = unite(name.infer() for name in names) debug.dbg('finder._names_to_types: %s -> %s', names, types) if not names and isinstance(self._context, AbstractInstanceContext): # handling __getattr__ / __getattribute__ return self._check_getattr(self._context) # Add isinstance and other if/assert knowledge. if not types and isinstance(self._name, tree.Name) and \ not isinstance(self._name_context, AbstractInstanceContext): flow_scope = self._name base_node = self._name_context.tree_node if base_node.type == 'comp_for': return types while True: flow_scope = get_parent_scope(flow_scope, include_flows=True) n = _check_flow_information(self._name_context, flow_scope, self._name, self._position) if n is not None: return n if flow_scope == base_node: break return types
def _equals_origin_scope(self): node = self._origin_scope while node is not None: if node == self._parser_scope or node == self.context: return True node = get_parent_scope(node) return False
def py__class__(self): # This differentiation is only necessary for Python2. Python3 does not # use a different method class. if isinstance(parser_utils.get_parent_scope(self.tree_node), tree.Class): name = 'METHOD_CLASS' else: name = 'FUNCTION_CLASS' return compiled.get_special_object(self.evaluator, name)
def get_parent_scope(node): try: # jedi 0.11 from jedi import parser_utils return parser_utils.get_parent_scope(node) except ImportError: # Older versions return node.get_parent_scope()
def py__class__(self): # This differentiation is only necessary for Python2. Python3 does not # use a different method class. if isinstance(parser_utils.get_parent_scope(self.tree_node), tree.Class): name = u'METHOD_CLASS' else: name = u'FUNCTION_CLASS' return compiled.get_special_object(self.evaluator, name)
def _is_name_reachable(self, name): if not name.is_definition(): return False parent = name.parent if parent.type == 'trailer': return False base_node = parent if parent.type in ('classdef', 'funcdef') else name return get_parent_scope(base_node) == self._parser_scope
def _find_definition(self, scope, name): from jedi import parser_utils # if the name is the name of a function definition if isinstance(scope, tree.Function): if scope.children[1] == name: return scope.children[1] # 0th child is keyword "def", 1st is name else: definition = self._get_def_from_function_params(scope, name) if definition: return definition for c in scope.children: if ( isinstance(c, tree.BaseNode) and c.type == "simple_stmt" and isinstance(c.children[0], tree.ImportName) ): for n in c.children[0].get_defined_names(): if n.value == name.value: return n # print(c.path_for_name(name.value)) if ( isinstance(c, tree.Function) and c.children[1].value == name.value and not isinstance(parser_utils.get_parent_scope(c), tree.Class) ): return c.children[1] if isinstance(c, tree.BaseNode) and c.type == "suite": for x in c.children: if self._is_global_stmt_with_name(x, name.value): return self._find_definition(parser_utils.get_parent_scope(scope), name) if isinstance(x, tree.Name) and x.is_definition() and x.value == name.value: return x def_candidate = self._find_def_in_simple_node(x, name) if def_candidate: return def_candidate if not isinstance(scope, tree.Module): return self._find_definition(parser_utils.get_parent_scope(scope), name) # if name itself is the left side of an assignment statement, then the name is the definition if name.is_definition(): return name return None
def _is_name_reachable(self, name): if not name.is_definition(): return False parent = name.parent if parent.type == 'trailer': return False base_node = parent if parent.type in ('classdef', 'funcdef') else name return get_parent_scope(base_node) == self._parser_scope
def find_usages_in_node(node, global_encountered=False): names = [] if isinstance(node, tree.BaseNode): if parser_utils.is_scope(node): global_encountered = False if node in searched_scopes: return names searched_scopes.add(node) if isinstance(node, tree.Function): d = self._get_def_from_function_params(node, name) if d and d != definition: return [] for c in node.children: dot_names = self._get_dot_names(c) if len(dot_names) > 1 and dot_names[1].value == name.value: continue sub_result = find_usages_in_node(c, global_encountered=global_encountered) if sub_result is None: if not parser_utils.is_scope(node): return ( None if definition and node != parser_utils.get_parent_scope(definition) else [definition] ) else: sub_result = [] names.extend(sub_result) if self._is_global_stmt_with_name(c, name.value): global_encountered = True elif isinstance(node, tree.Name) and node.value == name.value: if definition and definition != node: if self._is_name_function_definition(node): if isinstance( parser_utils.get_parent_scope(parser_utils.get_parent_scope(node)), tree.Class, ): return [] else: return None if ( node.is_definition() and not global_encountered and ( is_function_definition or parser_utils.get_parent_scope(node) != parser_utils.get_parent_scope(definition) ) ): return None if self._is_name_function_definition(definition) and isinstance( parser_utils.get_parent_scope(parser_utils.get_parent_scope(definition)), tree.Class, ): return None names.append(node) return names
def get_module_names(module, all_scopes): """ Returns a dictionary with name parts as keys and their call paths as values. """ names = chain.from_iterable(module.get_used_names().values()) if not all_scopes: # We have to filter all the names that don't have the module as a # parent_scope. There's None as a parent, because nodes in the module # node have the parent module and not suite as all the others. # Therefore it's important to catch that case. names = [n for n in names if get_parent_scope(n).parent in (module, None)] return names
def get_module_names(module, all_scopes): """ Returns a dictionary with name parts as keys and their call paths as values. """ names = chain.from_iterable(module.get_used_names().values()) if not all_scopes: # We have to filter all the names that don't have the module as a # parent_scope. There's None as a parent, because nodes in the module # node have the parent module and not suite as all the others. # Therefore it's important to catch that case. names = [n for n in names if get_parent_scope(n).parent in (module, None)] return names
def from_scope_node(scope_node, is_nested=True): if scope_node == self.tree_node: return self if scope_node.type in ('funcdef', 'lambdef', 'classdef'): return self.create_value(scope_node).as_context() elif scope_node.type in ('comp_for', 'sync_comp_for'): parent_scope = parser_utils.get_parent_scope(scope_node) parent_context = from_scope_node(parent_scope) if node.start_pos >= scope_node.children[-1].start_pos: return parent_context return CompForContext(parent_context, scope_node) raise Exception("There's a scope that was not managed: %s" % scope_node)
def _search_function_arguments(module_context, funcdef, string_name): """ Returns a list of param names. """ compare_node = funcdef if string_name == '__init__': cls = get_parent_scope(funcdef) if cls.type == 'classdef': string_name = cls.name.value compare_node = cls found_arguments = False i = 0 inference_state = module_context.inference_state if settings.dynamic_params_for_other_modules: module_contexts = get_module_contexts_containing_name( inference_state, [module_context], string_name, # Limit the amounts of files to be opened massively. limit_reduction=5, ) else: module_contexts = [module_context] for for_mod_context in module_contexts: for name, trailer in _get_potential_nodes(for_mod_context, string_name): i += 1 # This is a simple way to stop Jedi's dynamic param recursion # from going wild: The deeper Jedi's in the recursion, the less # code should be inferred. if i * inference_state.dynamic_params_depth > MAX_PARAM_SEARCHES: return random_context = for_mod_context.create_context(name) for arguments in _check_name_for_execution(inference_state, random_context, compare_node, name, trailer): found_arguments = True yield arguments # If there are results after processing a module, we're probably # good to process. This is a speed optimization. if found_arguments: return
def _check_for_additional_knowledge(self, name_or_str, name_context, position): name_context = name_context or self # Add isinstance and other if/assert knowledge. if isinstance(name_or_str, Name) and not name_context.is_instance(): flow_scope = name_or_str base_nodes = [name_context.tree_node] if any(b.type in ('comp_for', 'sync_comp_for') for b in base_nodes): return NO_VALUES from jedi.inference.finder import check_flow_information while True: flow_scope = get_parent_scope(flow_scope, include_flows=True) n = check_flow_information(name_context, flow_scope, name_or_str, position) if n is not None: return n if flow_scope in base_nodes: break return NO_VALUES
def create_instance_context(self, class_context, node): if node.parent.type in ('funcdef', 'classdef'): node = node.parent scope = get_parent_scope(node) if scope == class_context.tree_node: return class_context else: parent_context = self.create_instance_context(class_context, scope) if scope.type == 'funcdef': if scope.name.value == '__init__' and parent_context == class_context: return self._create_init_execution(class_context, scope) else: bound_method = BoundMethod(self.evaluator, self, class_context, self.parent_context, scope) return bound_method.get_function_execution() else: raise NotImplementedError return class_context
def create_instance_context(self, class_context, node): if node.parent.type in ('funcdef', 'classdef'): node = node.parent scope = get_parent_scope(node) if scope == class_context.tree_node: return class_context else: parent_context = self.create_instance_context(class_context, scope) if scope.type == 'funcdef': if scope.name.value == '__init__' and parent_context == class_context: return self._create_init_execution(class_context, scope) else: bound_method = BoundMethod( self.evaluator, self, class_context, self.parent_context, scope ) return bound_method.get_function_execution() else: raise NotImplementedError return class_context
def is_module_scope_name(name): parent_scope = get_parent_scope(name) if is_name_of_func_or_class_def(name, parent_scope): # XXX: In syntax tree function- and class-name nodes are immediate children of # their respective class-definition or function-definition nodes. Technically, # get_parent_scope(...) for them should return the parent of the definition node, # because # # def foo(...): pass # # is equivalent to # # foo = lambda(...): None # # but that would be a big change that could break type inference, whereas for now # this discrepancy looks like only a problem for "get_module_names". parent_scope = parent_scope.parent # async functions have an extra wrapper. Strip it. if parent_scope and parent_scope.type == 'async_stmt': parent_scope = parent_scope.parent return parent_scope in (module, None)
def _search_function_executions(evaluator, module_context, funcdef): """ Returns a list of param names. """ from jedi.evaluate import representation as er func_string_name = funcdef.name.value compare_node = funcdef if func_string_name == '__init__': cls = get_parent_scope(funcdef) if isinstance(cls, tree.Class): func_string_name = cls.name.value compare_node = cls found_executions = False i = 0 for for_mod_context in imports.get_modules_containing_name( evaluator, [module_context], func_string_name): if not isinstance(module_context, er.ModuleContext): return for name, trailer in _get_possible_nodes(for_mod_context, func_string_name): i += 1 # This is a simple way to stop Jedi's dynamic param recursion # from going wild: The deeper Jedi's in the recursion, the less # code should be evaluated. if i * evaluator.dynamic_params_depth > MAX_PARAM_SEARCHES: return random_context = evaluator.create_context(for_mod_context, name) for function_execution in _check_name_for_execution( evaluator, random_context, compare_node, name, trailer): found_executions = True yield function_execution # If there are results after processing a module, we're probably # good to process. This is a speed optimization. if found_executions: return
def _search_function_executions(evaluator, module_context, funcdef): """ Returns a list of param names. """ from jedi.evaluate import representation as er func_string_name = funcdef.name.value compare_node = funcdef if func_string_name == '__init__': cls = get_parent_scope(funcdef) if isinstance(cls, tree.Class): func_string_name = cls.name.value compare_node = cls found_executions = False i = 0 for for_mod_context in imports.get_modules_containing_name( evaluator, [module_context], func_string_name): if not isinstance(module_context, er.ModuleContext): return for name, trailer in _get_possible_nodes(for_mod_context, func_string_name): i += 1 # This is a simple way to stop Jedi's dynamic param recursion # from going wild: The deeper Jedi's in the recursion, the less # code should be evaluated. if i * evaluator.dynamic_params_depth > MAX_PARAM_SEARCHES: return random_context = evaluator.create_context(for_mod_context, name) for function_execution in _check_name_for_execution( evaluator, random_context, compare_node, name, trailer): found_executions = True yield function_execution # If there are results after processing a module, we're probably # good to process. This is a speed optimization. if found_executions: return
def tree_name_to_values(inference_state, context, tree_name): value_set = NO_VALUES module_node = context.get_root_context().tree_node # First check for annotations, like: `foo: int = 3` if module_node is not None: names = module_node.get_used_names().get(tree_name.value, []) found_annotation = False for name in names: expr_stmt = name.parent if expr_stmt.type == "expr_stmt" and expr_stmt.children[ 1].type == "annassign": correct_scope = parser_utils.get_parent_scope( name) == context.tree_node if correct_scope: found_annotation = True value_set |= annotation.infer_annotation( context, expr_stmt.children[1].children[1]).execute_annotation( ) if found_annotation: return value_set types = [] node = tree_name.get_definition(import_name_always=True, include_setitem=True) if node is None: node = tree_name.parent if node.type == 'global_stmt': c = context.create_context(tree_name) if c.is_module(): # In case we are already part of the module, there is no point # in looking up the global statement anymore, because it's not # valid at that point anyway. return NO_VALUES # For global_stmt lookups, we only need the first possible scope, # which means the function itself. filter = next(c.get_filters()) names = filter.get(tree_name.value) return ValueSet.from_sets(name.infer() for name in names) elif node.type not in ('import_from', 'import_name'): c = context.create_context(tree_name) return infer_atom(c, tree_name) typ = node.type if typ == 'for_stmt': types = annotation.find_type_from_comment_hint_for( context, node, tree_name) if types: return types if typ == 'with_stmt': types = annotation.find_type_from_comment_hint_with( context, node, tree_name) if types: return types if typ in ('for_stmt', 'comp_for', 'sync_comp_for'): try: types = context.predefined_names[node][tree_name.value] except KeyError: cn = ContextualizedNode(context, node.children[3]) for_types = iterate_values( cn.infer(), contextualized_node=cn, is_async=node.parent.type == 'async_stmt', ) n = TreeNameDefinition(context, tree_name) types = check_tuple_assignments(n, for_types) elif typ == 'expr_stmt': types = infer_expr_stmt(context, node, tree_name) elif typ == 'with_stmt': value_managers = context.infer_node( node.get_test_node_from_name(tree_name)) if node.parent.type == 'async_stmt': # In the case of `async with` statements, we need to # first get the coroutine from the `__aenter__` method, # then "unwrap" via the `__await__` method enter_methods = value_managers.py__getattribute__('__aenter__') coro = enter_methods.execute_with_values() return coro.py__await__().py__stop_iteration_returns() enter_methods = value_managers.py__getattribute__('__enter__') return enter_methods.execute_with_values() elif typ in ('import_from', 'import_name'): types = imports.infer_import(context, tree_name) elif typ in ('funcdef', 'classdef'): types = _apply_decorators(context, node) elif typ == 'try_stmt': # TODO an exception can also be a tuple. Check for those. # TODO check for types that are not classes and add it to # the static analysis report. exceptions = context.infer_node( tree_name.get_previous_sibling().get_previous_sibling()) types = exceptions.execute_with_values() elif typ == 'param': types = NO_VALUES elif typ == 'del_stmt': types = NO_VALUES elif typ == 'namedexpr_test': types = infer_node(context, node) else: raise ValueError("Should not happen. type: %s" % typ) return types
def _get_flow_scopes(node): while True: node = get_parent_scope(node, include_flows=True) if node is None or is_scope(node): return yield node
def _get_flow_scopes(node): while True: node = get_parent_scope(node, include_flows=True) if node is None or is_scope(node): return yield node
def is_module_scope_name(name): parent_scope = get_parent_scope(name) # async functions have an extra wrapper. Strip it. if parent_scope and parent_scope.type == 'async_stmt': parent_scope = parent_scope.parent return parent_scope in (module, None)
def tree_name_to_contexts(evaluator, context, tree_name): context_set = ContextSet() module_node = context.get_root_context().tree_node if module_node is not None: names = module_node.get_used_names().get(tree_name.value, []) for name in names: expr_stmt = name.parent correct_scope = parser_utils.get_parent_scope(name) == context.tree_node if expr_stmt.type == "expr_stmt" and expr_stmt.children[1].type == "annassign" and correct_scope: context_set |= _evaluate_for_annotation(context, expr_stmt.children[1].children[1]) if context_set: return context_set types = [] node = tree_name.get_definition(import_name_always=True) if node is None: node = tree_name.parent if node.type == 'global_stmt': context = evaluator.create_context(context, tree_name) finder = NameFinder(evaluator, context, context, tree_name.value) filters = finder.get_filters(search_global=True) # For global_stmt lookups, we only need the first possible scope, # which means the function itself. filters = [next(filters)] return finder.find(filters, attribute_lookup=False) elif node.type not in ('import_from', 'import_name'): raise ValueError("Should not happen. type: %s", node.type) typ = node.type if typ == 'for_stmt': types = pep0484.find_type_from_comment_hint_for(context, node, tree_name) if types: return types if typ == 'with_stmt': types = pep0484.find_type_from_comment_hint_with(context, node, tree_name) if types: return types if typ in ('for_stmt', 'comp_for'): try: types = context.predefined_names[node][tree_name.value] except KeyError: cn = ContextualizedNode(context, node.children[3]) for_types = iterate_contexts( cn.infer(), contextualized_node=cn, is_async=node.parent.type == 'async_stmt', ) c_node = ContextualizedName(context, tree_name) types = check_tuple_assignments(evaluator, c_node, for_types) elif typ == 'expr_stmt': types = _remove_statements(evaluator, context, node, tree_name) elif typ == 'with_stmt': context_managers = context.eval_node(node.get_test_node_from_name(tree_name)) enter_methods = context_managers.py__getattribute__(u'__enter__') return enter_methods.execute_evaluated() elif typ in ('import_from', 'import_name'): types = imports.infer_import(context, tree_name) elif typ in ('funcdef', 'classdef'): types = _apply_decorators(context, node) elif typ == 'try_stmt': # TODO an exception can also be a tuple. Check for those. # TODO check for types that are not classes and add it to # the static analysis report. exceptions = context.eval_node(tree_name.get_previous_sibling().get_previous_sibling()) types = exceptions.execute_evaluated() else: raise ValueError("Should not happen. type: %s" % typ) return types
def create_instance_context(self, class_context, node): if get_parent_scope(node).type == 'classdef': return class_context else: return super(CompiledInstance, self).create_instance_context(class_context, node)
def create_instance_context(self, class_context, node): if get_parent_scope(node).type == 'classdef': return class_context else: return super(CompiledInstance, self).create_instance_context(class_context, node)
def tree_name_to_contexts(evaluator, context, tree_name): context_set = NO_CONTEXTS module_node = context.get_root_context().tree_node # First check for annotations, like: `foo: int = 3` if module_node is not None: names = module_node.get_used_names().get(tree_name.value, []) for name in names: expr_stmt = name.parent if expr_stmt.type == "expr_stmt" and expr_stmt.children[ 1].type == "annassign": correct_scope = parser_utils.get_parent_scope( name) == context.tree_node if correct_scope: context_set |= annotation.eval_annotation( context, expr_stmt.children[1].children[1]).execute_annotation( ) if context_set: return context_set types = [] node = tree_name.get_definition(import_name_always=True) if node is None: node = tree_name.parent if node.type == 'global_stmt': context = evaluator.create_context(context, tree_name) finder = NameFinder(evaluator, context, context, tree_name.value) filters = finder.get_filters(search_global=True) # For global_stmt lookups, we only need the first possible scope, # which means the function itself. filters = [next(filters)] return finder.find(filters, attribute_lookup=False) elif node.type not in ('import_from', 'import_name'): context = evaluator.create_context(context, tree_name) return eval_atom(context, tree_name) typ = node.type if typ == 'for_stmt': types = annotation.find_type_from_comment_hint_for( context, node, tree_name) if types: return types if typ == 'with_stmt': types = annotation.find_type_from_comment_hint_with( context, node, tree_name) if types: return types if typ in ('for_stmt', 'comp_for', 'sync_comp_for'): try: types = context.predefined_names[node][tree_name.value] except KeyError: cn = ContextualizedNode(context, node.children[3]) for_types = iterate_contexts( cn.infer(), contextualized_node=cn, is_async=node.parent.type == 'async_stmt', ) c_node = ContextualizedName(context, tree_name) types = check_tuple_assignments(evaluator, c_node, for_types) elif typ == 'expr_stmt': types = _remove_statements(evaluator, context, node, tree_name) elif typ == 'with_stmt': context_managers = context.eval_node( node.get_test_node_from_name(tree_name)) enter_methods = context_managers.py__getattribute__(u'__enter__') return enter_methods.execute_evaluated() elif typ in ('import_from', 'import_name'): types = imports.infer_import(context, tree_name) elif typ in ('funcdef', 'classdef'): types = _apply_decorators(context, node) elif typ == 'try_stmt': # TODO an exception can also be a tuple. Check for those. # TODO check for types that are not classes and add it to # the static analysis report. exceptions = context.eval_node( tree_name.get_previous_sibling().get_previous_sibling()) types = exceptions.execute_evaluated() elif node.type == 'param': types = NO_CONTEXTS else: raise ValueError("Should not happen. type: %s" % typ) return types