def visit_functiondef(self, node: astroid.FunctionDef) -> None: node.inf_type = NoType() # Get the inferred type of the function arguments inferred_args = [ self.lookup_inf_type(node, arg) for arg in node.argnames() ] if isinstance(node.parent, astroid.ClassDef) and inferred_args: # first argument is special in these cases if node.type == 'method': self.type_constraints.unify(inferred_args[0], _ForwardRef(node.parent.name), node) elif node.type == 'classmethod': self.type_constraints.unify( inferred_args[0], Type[_ForwardRef(node.parent.name)], node) # Get inferred return type if any(node.nodes_of_class(astroid.Return)): return_node = list(node.nodes_of_class(astroid.Return))[-1] if isinstance(return_node.inf_type, TypeFail): inferred_return = return_node.inf_type else: inferred_return = self.lookup_inf_type(node, 'return') elif node.name == '__init__' and inferred_args: inferred_return = inferred_args[0] else: inferred_return = TypeInfo(type(None)) # Update the environment storing the function's type. polymorphic_tvars = [] for arg in inferred_args + [inferred_return]: arg >> (lambda a: polymorphic_tvars.append(a.__name__) if isinstance(a, TypeVar) else None) # Create function signature func_type = create_Callable_TypeResult(failable_collect(inferred_args), inferred_return, polymorphic_tvars) # Check for optional arguments, create a Union of function signatures if necessary num_defaults = len(node.args.defaults) if num_defaults > 0 and not isinstance(func_type, TypeFail): for i in range(num_defaults): opt_args = inferred_args[:-1 - i] opt_func_type = create_Callable_TypeResult( failable_collect(opt_args), inferred_return, polymorphic_tvars) func_type = func_type >> ( lambda f: opt_func_type >> (lambda opt_f: TypeInfo(Union[f, opt_f]))) # Final type signature unify func_name = self.lookup_inf_type(node.parent, node.name) result = self.type_constraints.unify(func_name, func_type, node) if isinstance(result, TypeFail): node.inf_type = result
def visit_functiondef(self, node: astroid.FunctionDef) -> None: node.inf_type = NoType() # Get the inferred type of the function arguments inferred_args = [self.lookup_inf_type(node, arg) for arg in node.argnames()] if isinstance(node.parent, astroid.ClassDef) and inferred_args: # first argument is special in these cases if node.type == 'method': self.type_constraints.unify(inferred_args[0], ForwardRef(node.parent.name), node) elif node.type == 'classmethod': self.type_constraints.unify(inferred_args[0], Type[ForwardRef(node.parent.name)], node) # Get inferred return type if any(node.nodes_of_class(astroid.Return)): return_node = list(node.nodes_of_class(astroid.Return))[-1] if isinstance(return_node.inf_type, TypeFail): inferred_return = return_node.inf_type else: inferred_return = self.lookup_inf_type(node, 'return') elif node.name == '__init__' and inferred_args: inferred_return = inferred_args[0] else: inferred_return = TypeInfo(type(None)) # Update the environment storing the function's type. polymorphic_tvars = set() for arg in inferred_args + [inferred_return]: arg >> ( lambda a: polymorphic_tvars.add(a.__name__) if isinstance(a, TypeVar) else None) # Create function signature func_type = create_Callable_TypeResult(failable_collect(inferred_args), inferred_return, polymorphic_tvars) # Check for optional arguments, create a Union of function signatures if necessary num_defaults = len(node.args.defaults) if num_defaults > 0 and not isinstance(func_type, TypeFail): for i in range(num_defaults): opt_args = inferred_args[:-1-i] opt_func_type = create_Callable_TypeResult(failable_collect(opt_args), inferred_return, polymorphic_tvars) func_type = func_type >> ( lambda f: opt_func_type >> ( lambda opt_f: TypeInfo(Union[f, opt_f]))) # Final type signature unify func_name = self.lookup_inf_type(node.parent, node.name) result = self.type_constraints.unify(func_name, func_type, node) if isinstance(result, TypeFail): node.inf_type = result
def _visit_functiondef(self, node: astroid.FunctionDef, match: TypeHintMatch) -> None: if node.name != match.function_name: return if node.is_method(): return if not match.module_filter.match(self.module): return # Check that at least one argument is annotated. annotations = _get_all_annotations(node) if node.returns is None and not _has_valid_annotations(annotations): return # Check that all arguments are correctly annotated. for key, expected_type in match.arg_types.items(): if not _is_valid_type(expected_type, annotations[key]): self.add_message( "hass-argument-type", node=node.args.args[key], args=(key + 1, expected_type), ) # Check the return type. if not _is_valid_type(return_type := match.return_type, node.returns): self.add_message("hass-return-type", node=node, args=return_type or "None")
def visit_functiondef(self, func: astroid.FunctionDef) -> None: self._current_block.add_statement(func) previous_cfg = self._current_cfg previous_block = self._current_block self.cfgs[func] = ControlFlowGraph() self._current_cfg = self.cfgs[func] self._control_boundaries.append((func, { astroid.Return.__name__: self._current_cfg.end })) self._current_cfg.start.add_statement(func.args) func.cfg_block = self._current_cfg.start self._current_block = self._current_cfg.create_block( self._current_cfg.start) for child in func.body: child.accept(self) self._control_boundaries.pop() self._current_cfg.link_or_merge(self._current_block, self._current_cfg.end) self._current_cfg.update_block_reachability() self._current_block = previous_block self._current_cfg = previous_cfg
def _set_function_def_environment(self, node: astroid.FunctionDef) -> None: """Method to set environment of a FunctionDef node.""" node.type_environment = Environment() # self is a special case if node.args.args and node.args.args[0].name == 'self' and isinstance(node.parent, astroid.ClassDef): node.type_environment.locals['self'] = _ForwardRef(node.parent.name) self._populate_local_env(node) node.type_environment.locals['return'] = self.type_constraints.fresh_tvar(node)
def _set_function_def_environment(self, node: astroid.FunctionDef) -> None: """Method to set environment of a FunctionDef node.""" node.type_environment = Environment() # self is a special case if node.args.args and node.args.args[0].name == 'self' and isinstance(node.parent, astroid.ClassDef): node.type_environment.locals['self'] = ForwardRef(node.parent.name) self._populate_local_env(node) self._populate_local_env_attrs(node) node.type_environment.locals['return'] = self.type_constraints.fresh_tvar(node)
def visit_functiondef(self, node: FunctionDef) -> None: """Called when a FunctionDef node is visited.""" if not node.is_method() or node.name != "__init__": return # Check that all arguments are annotated. # The first argument is "self". args = node.args annotations = (args.posonlyargs_annotations + args.annotations + args.kwonlyargs_annotations)[1:] if args.vararg is not None: annotations.append(args.varargannotation) if args.kwarg is not None: annotations.append(args.kwargannotation) if not annotations or None in annotations: return # Check that return type is specified and it is "None". if not isinstance(node.returns, Const) or node.returns.value is not None: self.add_message("hass-constructor-return", node=node)
def transform(node: FunctionDef): if is_validator_method(node): node.type = "classmethod"
def visit_functiondef(self, node: astroid.FunctionDef) -> None: node.inf_type = TypeInfo(NoType) # Get the inferred type of the function. inferred_args = [ self.lookup_type(node, arg) for arg in node.argnames() ] if isinstance(node.parent, astroid.ClassDef) and isinstance( inferred_args[0], TypeVar): # first argument is special in these cases if node.type == 'method': self.type_constraints.unify(inferred_args[0], _ForwardRef(node.parent.name), node) elif node.type == 'classmethod': self.type_constraints.unify( inferred_args[0], Type[_ForwardRef(node.parent.name)], node) if any(node.nodes_of_class(astroid.Return)): inferred_return = self.type_constraints.resolve( node.type_environment.lookup_in_env('return')).getValue() else: inferred_return = type(None) # Get any function type annotations. if any(annotation is not None for annotation in node.args.annotations): annotated_type = parse_annotations(node) else: annotated_type = None # Combine inferred and annotated types. if annotated_type: combined_args = [] for inferred, annotated in zip(inferred_args, annotated_type.__args__[:-1]): if annotated is None: annotated = type(None) t = self.type_constraints.unify(inferred, annotated, node).getValue() combined_args.append(t) annotated_rtype = annotated_type.__args__[-1] if annotated_rtype is None: annotated_rtype = type(None) combined_return = self.type_constraints.unify( inferred_return, annotated_rtype, node).getValue() else: combined_args, combined_return = inferred_args, inferred_return # Update the environment storing the function's type. polymorphic_tvars = [ arg for arg in combined_args if isinstance(arg, TypeVar) ] func_type = create_Callable(combined_args, combined_return, polymorphic_tvars) num_defaults = len(node.args.defaults) if num_defaults > 0: for i in range(num_defaults): opt_args = inferred_args[:-1 - i] opt_func_type = create_Callable(opt_args, combined_return, polymorphic_tvars) func_type = Union[func_type, opt_func_type] self.type_constraints.unify(self.lookup_type(node.parent, node.name), func_type, node)