Exemple #1
0
    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
Exemple #3
0
    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")
Exemple #4
0
    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
Exemple #5
0
 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)
Exemple #7
0
    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)
Exemple #8
0
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)