def create_name(self, tree_name): definition = tree_name.get_definition() if definition and definition.type == 'param' and definition.name == tree_name: funcdef = search_ancestor(definition, 'funcdef', 'lambdef') func = self.create_value(funcdef) return AnonymousParamName(func, tree_name) else: context = self.create_context(tree_name) return TreeNameDefinition(context, tree_name)
def _convert_names(self, names): for name in names: param = search_ancestor(name, 'param') # Here we don't need to check if the param is a default/annotation, # because those are not definitions and never make it to this # point. if param: yield self._convert_param(param, name) else: yield TreeNameDefinition(self.parent_context, name)
def _get_global_filters_for_name(context, name_or_none, position): # For functions and classes the defaults don't belong to the # function and get inferred in the value before the function. So # make sure to exclude the function/class name. if name_or_none is not None: ancestor = search_ancestor(name_or_none, 'funcdef', 'classdef', 'lambdef') lambdef = None if ancestor == 'lambdef': # For lambdas it's even more complicated since parts will # be inferred later. lambdef = ancestor ancestor = search_ancestor(name_or_none, 'funcdef', 'classdef') if ancestor is not None: colon = ancestor.children[-2] if position is not None and position < colon.start_pos: if lambdef is None or position < lambdef.children[-2].start_pos: position = ancestor.start_pos return get_global_filters(context, position, name_or_none)
def get_qualified_names(self, include_module_names=False): import_node = search_ancestor(self.tree_name, 'import_name', 'import_from') # For import nodes we cannot just have names, because it's very unclear # how they would look like. For now we just ignore them in most cases. # In case of level == 1, it works always, because it's like a submodule # lookup. if import_node is not None and not ( import_node.level == 1 and self.get_root_context().get_value().is_package()): # TODO improve the situation for when level is present. if include_module_names and not import_node.level: return tuple( n.value for n in import_node.get_path_for_name(self.tree_name)) else: return None return super(AbstractTreeName, self).get_qualified_names(include_module_names)
def _prepare_infer_import(module_context, tree_name): import_node = search_ancestor(tree_name, 'import_name', 'import_from') import_path = import_node.get_path_for_name(tree_name) from_import_name = None try: from_names = import_node.get_from_names() except AttributeError: # Is an import_name pass else: if len(from_names) + 1 == len(import_path): # We have to fetch the from_names part first and then check # if from_names exists in the modules. from_import_name = import_path[-1] import_path = from_names importer = Importer(module_context.inference_state, tuple(import_path), module_context, import_node.level) return from_import_name, tuple( import_path), import_node.level, importer.follow()
def check_flow_information(value, flow, search_name, pos): """ Try to find out the type of a variable just with the information that is given by the flows: e.g. It is also responsible for assert checks.:: if isinstance(k, str): k. # <- completion here ensures that `k` is a string. """ if not settings.dynamic_flow_information: return None result = None if is_scope(flow): # Check for asserts. module_node = flow.get_root_node() try: names = module_node.get_used_names()[search_name.value] except KeyError: return None names = reversed([ n for n in names if flow.start_pos <= n.start_pos < (pos or flow.end_pos) ]) for name in names: ass = search_ancestor(name, 'assert_stmt') if ass is not None: result = _check_isinstance_type(value, ass.assertion, search_name) if result is not None: return result if flow.type in ('if_stmt', 'while_stmt'): potential_ifs = [c for c in flow.children[1::4] if c != ':'] for if_test in reversed(potential_ifs): if search_name.start_pos > if_test.end_pos: return _check_isinstance_type(value, if_test, search_name) return result
def get_parent_function(self): """ Returns the function/lambda of a parameter. """ return search_ancestor(self, 'funcdef', 'lambdef')
def _get_param_node(self): return search_ancestor(self.tree_name, 'param')
def is_import(self): imp = search_ancestor(self.tree_name, 'import_from', 'import_name') return imp is not None
def goto(self): context = self.parent_context name = self.tree_name definition = name.get_definition(import_name_always=True) if definition is not None: type_ = definition.type if type_ == 'expr_stmt': # Only take the parent, because if it's more complicated than just # a name it's something you can "goto" again. is_simple_name = name.parent.type not in ('power', 'trailer') if is_simple_name: return [self] elif type_ in ('import_from', 'import_name'): from medi.inference.imports import goto_import module_names = goto_import(context, name) return module_names else: return [self] else: from medi.inference.imports import follow_error_node_imports_if_possible values = follow_error_node_imports_if_possible(context, name) if values is not None: return [value.name for value in values] par = name.parent node_type = par.type if node_type == 'argument' and par.children[1] == '=' and par.children[ 0] == name: # Named param goto. trailer = par.parent if trailer.type == 'arglist': trailer = trailer.parent if trailer.type != 'classdef': if trailer.type == 'decorator': value_set = context.infer_node(trailer.children[1]) else: i = trailer.parent.children.index(trailer) to_infer = trailer.parent.children[:i] if to_infer[0] == 'await': to_infer.pop(0) value_set = context.infer_node(to_infer[0]) from medi.inference.syntax_tree import infer_trailer for trailer in to_infer[1:]: value_set = infer_trailer(context, value_set, trailer) param_names = [] for value in value_set: for signature in value.get_signatures(): for param_name in signature.get_param_names(): if param_name.string_name == name.value: param_names.append(param_name) return param_names elif node_type == 'dotted_name': # Is a decorator. index = par.children.index(name) if index > 0: new_dotted = deep_ast_copy(par) new_dotted.children[index - 1:] = [] values = context.infer_node(new_dotted) return unite( value.goto(name, name_context=context) for value in values) if node_type == 'trailer' and par.children[0] == '.': values = infer_call_of_leaf(context, name, cut_own_trailer=True) return values.goto(name, name_context=context) else: stmt = search_ancestor(name, 'expr_stmt', 'lambdef') or name if stmt.type == 'lambdef': stmt = name return context.goto(name, position=stmt.start_pos)