示例#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
示例#2
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 = 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
示例#3
0
    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)