示例#1
0
def callable_type(fdef: FuncItem,
                  fallback: Instance,
                  ret_type: Optional[Type] = None) -> CallableType:
    # TODO: somewhat unfortunate duplication with prepare_method_signature in semanal
    if fdef.info and not fdef.is_static and fdef.arg_names:
        self_type = fill_typevars(fdef.info)  # type: Type
        if fdef.is_class or fdef.name == '__new__':
            self_type = TypeType.make_normalized(self_type)
        args = [
            self_type
        ] + [AnyType(TypeOfAny.unannotated)] * (len(fdef.arg_names) - 1)
    else:
        args = [AnyType(TypeOfAny.unannotated)] * len(fdef.arg_names)

    return CallableType(
        args,
        fdef.arg_kinds,
        [None if argument_elide_name(n) else n for n in fdef.arg_names],
        ret_type or AnyType(TypeOfAny.unannotated),
        fallback,
        name=fdef.name,
        line=fdef.line,
        column=fdef.column,
        implicit=True,
    )
示例#2
0
    def transform_args(
        self,
        n: ast27.arguments,
        line: int,
    ) -> Tuple[List[Argument], List[Statement]]:
        type_comments: Sequence[Optional[str]] = n.type_comments
        converter = TypeConverter(self.errors,
                                  line=line,
                                  assume_str_is_unicode=self.unicode_literals)
        decompose_stmts: List[Statement] = []

        n_args = n.args
        args = [(self.convert_arg(i, arg, line, decompose_stmts),
                 self.get_type(i, type_comments, converter))
                for i, arg in enumerate(n_args)]
        defaults = self.translate_expr_list(n.defaults)
        names: List[str] = [
            name for arg in n_args for name in self.extract_names(arg)
        ]

        new_args: List[Argument] = []
        num_no_defaults = len(args) - len(defaults)
        # positional arguments without defaults
        for a, annotation in args[:num_no_defaults]:
            new_args.append(Argument(a, annotation, None, ARG_POS))

        # positional arguments with defaults
        for (a, annotation), d in zip(args[num_no_defaults:], defaults):
            new_args.append(Argument(a, annotation, d, ARG_OPT))

        # *arg
        if n.vararg is not None:
            new_args.append(
                Argument(Var(n.vararg),
                         self.get_type(len(args), type_comments, converter),
                         None, ARG_STAR))
            names.append(n.vararg)

        # **kwarg
        if n.kwarg is not None:
            typ = self.get_type(
                len(args) + (0 if n.vararg is None else 1), type_comments,
                converter)
            new_args.append(Argument(Var(n.kwarg), typ, None, ARG_STAR2))
            names.append(n.kwarg)

        for arg in new_args:
            if argument_elide_name(arg.variable.name):
                arg.pos_only = True

        # We don't have any context object to give, but we have closed around the line num
        def fail_arg(msg: str, arg: None) -> None:
            self.fail(msg, line, 0)

        check_arg_names(names, [None] * len(names), fail_arg)

        return new_args, decompose_stmts
示例#3
0
    def visit_FunctionDef(self, n: ast27.FunctionDef) -> Statement:
        converter = TypeConverter(self.errors, line=n.lineno)
        args, decompose_stmts = self.transform_args(n.args, n.lineno)

        arg_kinds = [arg.kind for arg in args]
        arg_names = [arg.variable.name() for arg in args]  # type: List[Optional[str]]
        arg_names = [None if argument_elide_name(name) else name for name in arg_names]
        if special_function_elide_names(n.name):
            arg_names = [None] * len(arg_names)

        arg_types = []  # type: List[Optional[Type]]
        if (n.decorator_list and any(is_no_type_check_decorator(d) for d in n.decorator_list)):
            arg_types = [None] * len(args)
            return_type = None
        elif n.type_comment is not None and len(n.type_comment) > 0:
            try:
                func_type_ast = ast3.parse(n.type_comment, '<func_type>', 'func_type')
                assert isinstance(func_type_ast, ast3.FunctionType)
                # for ellipsis arg
                if (len(func_type_ast.argtypes) == 1 and
                        isinstance(func_type_ast.argtypes[0], ast3.Ellipsis)):
                    arg_types = [a.type_annotation
                                 if a.type_annotation is not None
                                 else AnyType(TypeOfAny.unannotated)
                                 for a in args]
                else:
                    # PEP 484 disallows both type annotations and type comments
                    if any(a.type_annotation is not None for a in args):
                        self.fail(messages.DUPLICATE_TYPE_SIGNATURES, n.lineno, n.col_offset)
                    arg_types = [a if a is not None else AnyType(TypeOfAny.unannotated) for
                                 a in converter.translate_expr_list(func_type_ast.argtypes)]
                return_type = converter.visit(func_type_ast.returns)

                # add implicit self type
                if self.in_class() and len(arg_types) < len(args):
                    arg_types.insert(0, AnyType(TypeOfAny.special_form))
            except SyntaxError:
                self.fail(TYPE_COMMENT_SYNTAX_ERROR, n.lineno, n.col_offset)
                arg_types = [AnyType(TypeOfAny.from_error)] * len(args)
                return_type = AnyType(TypeOfAny.from_error)
        else:
            arg_types = [a.type_annotation for a in args]
            return_type = converter.visit(None)

        for arg, arg_type in zip(args, arg_types):
            self.set_type_optional(arg_type, arg.initializer)

        func_type = None
        if any(arg_types) or return_type:
            if len(arg_types) != 1 and any(isinstance(t, EllipsisType) for t in arg_types):
                self.fail("Ellipses cannot accompany other argument types "
                          "in function type signature.", n.lineno, 0)
            elif len(arg_types) > len(arg_kinds):
                self.fail('Type signature has too many arguments', n.lineno, 0)
            elif len(arg_types) < len(arg_kinds):
                self.fail('Type signature has too few arguments', n.lineno, 0)
            else:
                any_type = AnyType(TypeOfAny.unannotated)
                func_type = CallableType([a if a is not None else any_type for a in arg_types],
                                        arg_kinds,
                                        arg_names,
                                        return_type if return_type is not None else any_type,
                                        _dummy_fallback)

        body = self.as_required_block(n.body, n.lineno)
        if decompose_stmts:
            body.body = decompose_stmts + body.body
        func_def = FuncDef(n.name,
                       args,
                       body,
                       func_type)
        if func_type is not None:
            func_type.definition = func_def
            func_type.line = n.lineno

        if n.decorator_list:
            var = Var(func_def.name())
            var.is_ready = False
            var.set_line(n.decorator_list[0].lineno)

            func_def.is_decorated = True
            func_def.set_line(n.lineno + len(n.decorator_list))
            func_def.body.set_line(func_def.get_line())
            return Decorator(func_def, self.translate_expr_list(n.decorator_list), var)
        else:
            return func_def
示例#4
0
    def do_func_def(self,
                    n: Union[ast3.FunctionDef, ast3.AsyncFunctionDef],
                    is_coroutine: bool = False) -> Union[FuncDef, Decorator]:
        """Helper shared between visit_FunctionDef and visit_AsyncFunctionDef."""
        no_type_check = bool(
            n.decorator_list
            and any(is_no_type_check_decorator(d) for d in n.decorator_list))

        args = self.transform_args(n.args,
                                   n.lineno,
                                   no_type_check=no_type_check)

        arg_kinds = [arg.kind for arg in args]
        arg_names = [arg.variable.name()
                     for arg in args]  # type: List[Optional[str]]
        arg_names = [
            None if argument_elide_name(name) else name for name in arg_names
        ]
        if special_function_elide_names(n.name):
            arg_names = [None] * len(arg_names)
        arg_types = None  # type: List[Type]
        if no_type_check:
            arg_types = [None] * len(args)
            return_type = None
        elif n.type_comment is not None:
            try:
                func_type_ast = ast3.parse(n.type_comment, '<func_type>',
                                           'func_type')
                assert isinstance(func_type_ast, ast3.FunctionType)
                # for ellipsis arg
                if (len(func_type_ast.argtypes) == 1 and isinstance(
                        func_type_ast.argtypes[0], ast3.Ellipsis)):
                    if n.returns:
                        # PEP 484 disallows both type annotations and type comments
                        self.fail(messages.DUPLICATE_TYPE_SIGNATURES, n.lineno,
                                  n.col_offset)
                    arg_types = [
                        a.type_annotation
                        if a.type_annotation is not None else AnyType()
                        for a in args
                    ]
                else:
                    # PEP 484 disallows both type annotations and type comments
                    if n.returns or any(a.type_annotation is not None
                                        for a in args):
                        self.fail(messages.DUPLICATE_TYPE_SIGNATURES, n.lineno,
                                  n.col_offset)
                    translated_args = (TypeConverter(
                        self.errors, line=n.lineno).translate_expr_list(
                            func_type_ast.argtypes))
                    arg_types = [
                        a if a is not None else AnyType()
                        for a in translated_args
                    ]
                return_type = TypeConverter(self.errors, line=n.lineno).visit(
                    func_type_ast.returns)

                # add implicit self type
                if self.in_class() and len(arg_types) < len(args):
                    arg_types.insert(0, AnyType())
            except SyntaxError:
                self.fail(TYPE_COMMENT_SYNTAX_ERROR, n.lineno, n.col_offset)
                arg_types = [AnyType()] * len(args)
                return_type = AnyType()
        else:
            arg_types = [a.type_annotation for a in args]
            return_type = TypeConverter(self.errors,
                                        line=n.lineno).visit(n.returns)

        for arg, arg_type in zip(args, arg_types):
            self.set_type_optional(arg_type, arg.initializer)

        if isinstance(return_type, UnboundType):
            return_type.is_ret_type = True

        func_type = None
        if any(arg_types) or return_type:
            if len(arg_types) != 1 and any(
                    isinstance(t, EllipsisType) for t in arg_types):
                self.fail(
                    "Ellipses cannot accompany other argument types "
                    "in function type signature.", n.lineno, 0)
            elif len(arg_types) > len(arg_kinds):
                self.fail('Type signature has too many arguments', n.lineno, 0)
            elif len(arg_types) < len(arg_kinds):
                self.fail('Type signature has too few arguments', n.lineno, 0)
            else:
                func_type = CallableType(
                    [
                        a if a is not None else AnyType(implicit=True)
                        for a in arg_types
                    ], arg_kinds, arg_names,
                    return_type if return_type is not None else AnyType(
                        implicit=True), None)

        func_def = FuncDef(n.name, args, self.as_block(n.body, n.lineno),
                           func_type)
        if is_coroutine:
            # A coroutine is also a generator, mostly for internal reasons.
            func_def.is_generator = func_def.is_coroutine = True
        if func_type is not None:
            func_type.definition = func_def
            func_type.line = n.lineno

        if n.decorator_list:
            var = Var(func_def.name())
            var.is_ready = False
            var.set_line(n.decorator_list[0].lineno)

            func_def.is_decorated = True
            func_def.set_line(n.lineno + len(n.decorator_list))
            func_def.body.set_line(func_def.get_line())
            return Decorator(func_def,
                             self.translate_expr_list(n.decorator_list), var)
        else:
            return func_def
示例#5
0
    def visit_FunctionDef(self, n: ast27.FunctionDef) -> Statement:
        self.class_and_function_stack.append('F')
        lineno = n.lineno
        converter = TypeConverter(self.errors,
                                  line=lineno,
                                  assume_str_is_unicode=self.unicode_literals)
        args, decompose_stmts = self.transform_args(n.args, lineno)

        arg_kinds = [arg.kind for arg in args]
        arg_names = [arg.variable.name()
                     for arg in args]  # type: List[Optional[str]]
        arg_names = [
            None if argument_elide_name(name) else name for name in arg_names
        ]
        if special_function_elide_names(n.name):
            arg_names = [None] * len(arg_names)

        arg_types = []  # type: List[Optional[Type]]
        type_comment = n.type_comment
        if (n.decorator_list and any(
                is_no_type_check_decorator(d) for d in n.decorator_list)):
            arg_types = [None] * len(args)
            return_type = None
        elif type_comment is not None and len(type_comment) > 0:
            try:
                func_type_ast = ast3_parse(type_comment, '<func_type>',
                                           'func_type')
                assert isinstance(func_type_ast, ast3.FunctionType)
                # for ellipsis arg
                if (len(func_type_ast.argtypes) == 1 and isinstance(
                        func_type_ast.argtypes[0], ast3.Ellipsis)):
                    arg_types = [
                        a.type_annotation if a.type_annotation is not None else
                        AnyType(TypeOfAny.unannotated) for a in args
                    ]
                else:
                    # PEP 484 disallows both type annotations and type comments
                    if any(a.type_annotation is not None for a in args):
                        self.fail(message_registry.DUPLICATE_TYPE_SIGNATURES,
                                  lineno, n.col_offset)
                    arg_types = [
                        a if a is not None else AnyType(TypeOfAny.unannotated)
                        for a in converter.translate_expr_list(
                            func_type_ast.argtypes)
                    ]
                return_type = converter.visit(func_type_ast.returns)

                # add implicit self type
                if self.in_method_scope() and len(arg_types) < len(args):
                    arg_types.insert(0, AnyType(TypeOfAny.special_form))
            except SyntaxError:
                stripped_type = type_comment.split("#", 2)[0].strip()
                err_msg = "{} '{}'".format(TYPE_COMMENT_SYNTAX_ERROR,
                                           stripped_type)
                self.fail(err_msg, lineno, n.col_offset)
                arg_types = [AnyType(TypeOfAny.from_error)] * len(args)
                return_type = AnyType(TypeOfAny.from_error)
        else:
            arg_types = [a.type_annotation for a in args]
            return_type = converter.visit(None)

        for arg, arg_type in zip(args, arg_types):
            self.set_type_optional(arg_type, arg.initializer)

        func_type = None
        if any(arg_types) or return_type:
            if len(arg_types) != 1 and any(
                    isinstance(t, EllipsisType) for t in arg_types):
                self.fail(
                    "Ellipses cannot accompany other argument types "
                    "in function type signature.", lineno, 0)
            elif len(arg_types) > len(arg_kinds):
                self.fail('Type signature has too many arguments',
                          lineno,
                          0,
                          blocker=False)
            elif len(arg_types) < len(arg_kinds):
                self.fail('Type signature has too few arguments',
                          lineno,
                          0,
                          blocker=False)
            else:
                any_type = AnyType(TypeOfAny.unannotated)
                func_type = CallableType(
                    [a if a is not None else any_type
                     for a in arg_types], arg_kinds, arg_names,
                    return_type if return_type is not None else any_type,
                    _dummy_fallback)

        body = self.as_required_block(n.body, lineno)
        if decompose_stmts:
            body.body = decompose_stmts + body.body
        func_def = FuncDef(n.name, args, body, func_type)
        if isinstance(func_def.type, CallableType):
            # semanal.py does some in-place modifications we want to avoid
            func_def.unanalyzed_type = func_def.type.copy_modified()
        if func_type is not None:
            func_type.definition = func_def
            func_type.line = lineno

        if n.decorator_list:
            var = Var(func_def.name())
            var.is_ready = False
            var.set_line(n.decorator_list[0].lineno)

            func_def.is_decorated = True
            func_def.set_line(lineno + len(n.decorator_list))
            func_def.body.set_line(func_def.get_line())
            dec = Decorator(func_def,
                            self.translate_expr_list(n.decorator_list), var)
            dec.set_line(lineno, n.col_offset)
            retval = dec  # type: Statement
        else:
            # Overrides set_line -- can't use self.set_line
            func_def.set_line(lineno, n.col_offset)
            retval = func_def
        self.class_and_function_stack.pop()
        return retval
示例#6
0
    def visit_FunctionDef(self, n: ast27.FunctionDef) -> Statement:
        lineno = n.lineno
        converter = TypeConverter(self.errors, line=lineno,
                                  assume_str_is_unicode=self.unicode_literals)
        args, decompose_stmts = self.transform_args(n.args, lineno)

        arg_kinds = [arg.kind for arg in args]
        arg_names = [arg.variable.name() for arg in args]  # type: List[Optional[str]]
        arg_names = [None if argument_elide_name(name) else name for name in arg_names]
        if special_function_elide_names(n.name):
            arg_names = [None] * len(arg_names)

        arg_types = []  # type: List[Optional[Type]]
        type_comment = n.type_comment
        if (n.decorator_list and any(is_no_type_check_decorator(d) for d in n.decorator_list)):
            arg_types = [None] * len(args)
            return_type = None
        elif type_comment is not None and len(type_comment) > 0:
            try:
                func_type_ast = ast3_parse(type_comment, '<func_type>', 'func_type')
                assert isinstance(func_type_ast, ast3.FunctionType)
                # for ellipsis arg
                if (len(func_type_ast.argtypes) == 1 and
                        isinstance(func_type_ast.argtypes[0], ast3.Ellipsis)):
                    arg_types = [a.type_annotation
                                 if a.type_annotation is not None
                                 else AnyType(TypeOfAny.unannotated)
                                 for a in args]
                else:
                    # PEP 484 disallows both type annotations and type comments
                    if any(a.type_annotation is not None for a in args):
                        self.fail(message_registry.DUPLICATE_TYPE_SIGNATURES, lineno, n.col_offset)
                    arg_types = [a if a is not None else AnyType(TypeOfAny.unannotated) for
                                 a in converter.translate_expr_list(func_type_ast.argtypes)]
                return_type = converter.visit(func_type_ast.returns)

                # add implicit self type
                if self.in_class() and len(arg_types) < len(args):
                    arg_types.insert(0, AnyType(TypeOfAny.special_form))
            except SyntaxError:
                self.fail(TYPE_COMMENT_SYNTAX_ERROR, lineno, n.col_offset)
                arg_types = [AnyType(TypeOfAny.from_error)] * len(args)
                return_type = AnyType(TypeOfAny.from_error)
        else:
            arg_types = [a.type_annotation for a in args]
            return_type = converter.visit(None)

        for arg, arg_type in zip(args, arg_types):
            self.set_type_optional(arg_type, arg.initializer)

        func_type = None
        if any(arg_types) or return_type:
            if len(arg_types) != 1 and any(isinstance(t, EllipsisType) for t in arg_types):
                self.fail("Ellipses cannot accompany other argument types "
                          "in function type signature.", lineno, 0)
            elif len(arg_types) > len(arg_kinds):
                self.fail('Type signature has too many arguments', lineno, 0)
            elif len(arg_types) < len(arg_kinds):
                self.fail('Type signature has too few arguments', lineno, 0)
            else:
                any_type = AnyType(TypeOfAny.unannotated)
                func_type = CallableType([a if a is not None else any_type for a in arg_types],
                                        arg_kinds,
                                        arg_names,
                                        return_type if return_type is not None else any_type,
                                        _dummy_fallback)

        body = self.as_required_block(n.body, lineno)
        if decompose_stmts:
            body.body = decompose_stmts + body.body
        func_def = FuncDef(n.name,
                       args,
                       body,
                       func_type)
        if isinstance(func_def.type, CallableType):
            # semanal.py does some in-place modifications we want to avoid
            func_def.unanalyzed_type = func_def.type.copy_modified()
        if func_type is not None:
            func_type.definition = func_def
            func_type.line = lineno

        if n.decorator_list:
            var = Var(func_def.name())
            var.is_ready = False
            var.set_line(n.decorator_list[0].lineno)

            func_def.is_decorated = True
            func_def.set_line(lineno + len(n.decorator_list))
            func_def.body.set_line(func_def.get_line())
            dec = Decorator(func_def, self.translate_expr_list(n.decorator_list), var)
            dec.set_line(lineno, n.col_offset)
            return dec
        else:
            # Overrides set_line -- can't use self.set_line
            func_def.set_line(lineno, n.col_offset)
            return func_def
示例#7
0
    def visit_FunctionDef(self, n: ast27.FunctionDef) -> Statement:
        converter = TypeConverter(line=n.lineno)
        args = self.transform_args(n.args, n.lineno)

        arg_kinds = [arg.kind for arg in args]
        arg_names = [arg.variable.name() for arg in args]  # type: List[Optional[str]]
        arg_names = [None if argument_elide_name(name) else name for name in arg_names]
        if special_function_elide_names(n.name):
            arg_names = [None] * len(arg_names)

        arg_types = None  # type: List[Type]
        if n.type_comment is not None and len(n.type_comment) > 0:
            try:
                func_type_ast = ast35.parse(n.type_comment, '<func_type>', 'func_type')
            except SyntaxError:
                raise TypeCommentParseError(TYPE_COMMENT_SYNTAX_ERROR, n.lineno, n.col_offset)
            assert isinstance(func_type_ast, ast35.FunctionType)
            # for ellipsis arg
            if (len(func_type_ast.argtypes) == 1 and
                    isinstance(func_type_ast.argtypes[0], ast35.Ellipsis)):
                arg_types = [a.type_annotation if a.type_annotation is not None else AnyType()
                             for a in args]
            else:
                arg_types = [a if a is not None else AnyType() for
                            a in converter.translate_expr_list(func_type_ast.argtypes)]
            return_type = converter.visit(func_type_ast.returns)

            # add implicit self type
            if self.in_class() and len(arg_types) < len(args):
                arg_types.insert(0, AnyType())
        else:
            arg_types = [a.type_annotation for a in args]
            return_type = converter.visit(None)

        for arg, arg_type in zip(args, arg_types):
            self.set_type_optional(arg_type, arg.initializer)

        if isinstance(return_type, UnboundType):
            return_type.is_ret_type = True

        func_type = None
        if any(arg_types) or return_type:
            if len(arg_types) > len(arg_kinds):
                raise FastParserError('Type signature has too many arguments', n.lineno, offset=0)
            if len(arg_types) < len(arg_kinds):
                raise FastParserError('Type signature has too few arguments', n.lineno, offset=0)
            func_type = CallableType([a if a is not None else AnyType() for a in arg_types],
                                     arg_kinds,
                                     arg_names,
                                     return_type if return_type is not None else AnyType(),
                                     None)

        func_def = FuncDef(n.name,
                       args,
                       self.as_block(n.body, n.lineno),
                       func_type)
        if func_type is not None:
            func_type.definition = func_def
            func_type.line = n.lineno

        if n.decorator_list:
            var = Var(func_def.name())
            var.is_ready = False
            var.set_line(n.decorator_list[0].lineno)

            func_def.is_decorated = True
            func_def.set_line(n.lineno + len(n.decorator_list))
            func_def.body.set_line(func_def.get_line())
            return Decorator(func_def, self.translate_expr_list(n.decorator_list), var)
        else:
            return func_def
示例#8
0
    def do_func_def(self, n: Union[ast35.FunctionDef, ast35.AsyncFunctionDef],
                    is_coroutine: bool = False) -> Union[FuncDef, Decorator]:
        """Helper shared between visit_FunctionDef and visit_AsyncFunctionDef."""
        no_type_check = bool(n.decorator_list and
                             any(is_no_type_check_decorator(d) for d in n.decorator_list))

        args = self.transform_args(n.args, n.lineno, no_type_check=no_type_check)

        arg_kinds = [arg.kind for arg in args]
        arg_names = [arg.variable.name() for arg in args]  # type: List[Optional[str]]
        arg_names = [None if argument_elide_name(name) else name for name in arg_names]
        if special_function_elide_names(n.name):
            arg_names = [None] * len(arg_names)
        arg_types = None  # type: List[Type]
        if no_type_check:
            arg_types = [None] * len(args)
            return_type = None
        elif n.type_comment is not None:
            try:
                func_type_ast = ast35.parse(n.type_comment, '<func_type>', 'func_type')
                assert isinstance(func_type_ast, ast35.FunctionType)
                # for ellipsis arg
                if (len(func_type_ast.argtypes) == 1 and
                        isinstance(func_type_ast.argtypes[0], ast35.Ellipsis)):
                    if n.returns:
                        # PEP 484 disallows both type annotations and type comments
                        self.fail(messages.DUPLICATE_TYPE_SIGNATURES, n.lineno, n.col_offset)
                    arg_types = [a.type_annotation if a.type_annotation is not None else AnyType()
                                 for a in args]
                else:
                    # PEP 484 disallows both type annotations and type comments
                    if n.returns or any(a.type_annotation is not None for a in args):
                        self.fail(messages.DUPLICATE_TYPE_SIGNATURES, n.lineno, n.col_offset)
                    translated_args = (TypeConverter(self.errors, line=n.lineno)
                                       .translate_expr_list(func_type_ast.argtypes))
                    arg_types = [a if a is not None else AnyType()
                                for a in translated_args]
                return_type = TypeConverter(self.errors,
                                            line=n.lineno).visit(func_type_ast.returns)

                # add implicit self type
                if self.in_class() and len(arg_types) < len(args):
                    arg_types.insert(0, AnyType())
            except SyntaxError:
                self.fail(TYPE_COMMENT_SYNTAX_ERROR, n.lineno, n.col_offset)
                arg_types = [AnyType()] * len(args)
                return_type = AnyType()
        else:
            arg_types = [a.type_annotation for a in args]
            return_type = TypeConverter(self.errors, line=n.lineno).visit(n.returns)

        for arg, arg_type in zip(args, arg_types):
            self.set_type_optional(arg_type, arg.initializer)

        if isinstance(return_type, UnboundType):
            return_type.is_ret_type = True

        func_type = None
        if any(arg_types) or return_type:
            if len(arg_types) != 1 and any(isinstance(t, EllipsisType) for t in arg_types):
                self.fail("Ellipses cannot accompany other argument types "
                          "in function type signature.", n.lineno, 0)
            elif len(arg_types) > len(arg_kinds):
                self.fail('Type signature has too many arguments', n.lineno, 0)
            elif len(arg_types) < len(arg_kinds):
                self.fail('Type signature has too few arguments', n.lineno, 0)
            else:
                func_type = CallableType([a if a is not None else
                                          AnyType(implicit=True) for a in arg_types],
                                         arg_kinds,
                                         arg_names,
                                         return_type if return_type is not None else
                                         AnyType(implicit=True),
                                         None)

        func_def = FuncDef(n.name,
                       args,
                       self.as_block(n.body, n.lineno),
                       func_type)
        if is_coroutine:
            # A coroutine is also a generator, mostly for internal reasons.
            func_def.is_generator = func_def.is_coroutine = True
        if func_type is not None:
            func_type.definition = func_def
            func_type.line = n.lineno

        if n.decorator_list:
            var = Var(func_def.name())
            var.is_ready = False
            var.set_line(n.decorator_list[0].lineno)

            func_def.is_decorated = True
            func_def.set_line(n.lineno + len(n.decorator_list))
            func_def.body.set_line(func_def.get_line())
            return Decorator(func_def, self.translate_expr_list(n.decorator_list), var)
        else:
            return func_def
示例#9
0
    def do_func_def(self,
                    n: Union[ast3.FunctionDef, ast3.AsyncFunctionDef],
                    is_coroutine: bool = False) -> Union[FuncDef, Decorator]:
        """Helper shared between visit_FunctionDef and visit_AsyncFunctionDef."""
        no_type_check = bool(
            n.decorator_list
            and any(is_no_type_check_decorator(d) for d in n.decorator_list))

        args = self.transform_args(n.args,
                                   n.lineno,
                                   no_type_check=no_type_check)

        arg_kinds = [arg.kind for arg in args]
        arg_names = [arg.variable.name()
                     for arg in args]  # type: List[Optional[str]]
        arg_names = [
            None if argument_elide_name(name) else name for name in arg_names
        ]
        if special_function_elide_names(n.name):
            arg_names = [None] * len(arg_names)
        arg_types = []  # type: List[Optional[Type]]
        if no_type_check:
            arg_types = [None] * len(args)
            return_type = None
        elif n.type_comment is not None:
            try:
                func_type_ast = ast3.parse(n.type_comment, '<func_type>',
                                           'func_type')
                assert isinstance(func_type_ast, ast3.FunctionType)
                # for ellipsis arg
                if (len(func_type_ast.argtypes) == 1 and isinstance(
                        func_type_ast.argtypes[0], ast3.Ellipsis)):
                    if n.returns:
                        # PEP 484 disallows both type annotations and type comments
                        self.fail(errorcode.DUPLICATE_TYPE_SIGNATURES(),
                                  n.lineno, n.col_offset)
                    arg_types = [
                        a.type_annotation if a.type_annotation is not None else
                        AnyType(TypeOfAny.unannotated) for a in args
                    ]
                else:
                    # PEP 484 disallows both type annotations and type comments
                    if n.returns or any(a.type_annotation is not None
                                        for a in args):
                        self.fail(errorcode.DUPLICATE_TYPE_SIGNATURES(),
                                  n.lineno, n.col_offset)
                    translated_args = (TypeConverter(
                        self.errors, line=n.lineno).translate_expr_list(
                            func_type_ast.argtypes))
                    arg_types = [
                        a if a is not None else AnyType(TypeOfAny.unannotated)
                        for a in translated_args
                    ]
                return_type = TypeConverter(self.errors, line=n.lineno).visit(
                    func_type_ast.returns)

                # add implicit self type
                if self.in_class() and len(arg_types) < len(args):
                    arg_types.insert(0, AnyType(TypeOfAny.special_form))
            except SyntaxError:
                self.fail(errorcode.SYNTAX_ERROR_TYPE_COMMENT(), n.lineno,
                          n.col_offset)
                if n.type_comment and n.type_comment[0] != "(":
                    self.note(
                        errorcode.MSG_SHOW(
                            'Suggestion: wrap argument types in parentheses'),
                        n.lineno, n.col_offset)
                arg_types = [AnyType(TypeOfAny.from_error)] * len(args)
                return_type = AnyType(TypeOfAny.from_error)
        else:
            arg_types = [a.type_annotation for a in args]
            return_type = TypeConverter(
                self.errors,
                line=n.returns.lineno if n.returns else n.lineno).visit(
                    n.returns)

        for arg, arg_type in zip(args, arg_types):
            self.set_type_optional(arg_type, arg.initializer)

        func_type = None
        if any(arg_types) or return_type:
            if len(arg_types) != 1 and any(
                    isinstance(t, EllipsisType) for t in arg_types):
                self.fail(
                    errorcode.
                    ELLIPSES_CANNOT_ACC_OTHER_ARG_TYPES_IN_FUNCTION_TYPE_SIGNATURE(
                    ), n.lineno, 0)
            elif len(arg_types) > len(arg_kinds):
                self.fail(errorcode.TYPE_SIGNATURE_HAS_TOO_MANY_ARGUMENTS(),
                          n.lineno, 0)
            elif len(arg_types) < len(arg_kinds):
                self.fail(errorcode.TYPE_SIGNATURE_HAS_TOO_FEW_ARGUMENTS(),
                          n.lineno, 0)
            else:
                func_type = CallableType([
                    a if a is not None else AnyType(TypeOfAny.unannotated)
                    for a in arg_types
                ], arg_kinds, arg_names, return_type if return_type is not None
                                         else AnyType(TypeOfAny.unannotated),
                                         _dummy_fallback)

        func_def = FuncDef(n.name, args,
                           self.as_required_block(n.body, n.lineno), func_type)
        if is_coroutine:
            # A coroutine is also a generator, mostly for internal reasons.
            func_def.is_generator = func_def.is_coroutine = True
        if func_type is not None:
            func_type.definition = func_def
            func_type.line = n.lineno

        if n.decorator_list:
            var = Var(func_def.name())
            var.is_ready = False
            var.set_line(n.decorator_list[0].lineno)

            func_def.is_decorated = True
            func_def.set_line(n.lineno + len(n.decorator_list))
            func_def.body.set_line(func_def.get_line())
            return Decorator(func_def,
                             self.translate_expr_list(n.decorator_list), var)
        else:
            return func_def
示例#10
0
    def visit_FunctionDef(self, n: ast27.FunctionDef) -> Statement:
        converter = TypeConverter(self.errors, line=n.lineno)
        args, decompose_stmts = self.transform_args(n.args, n.lineno)

        arg_kinds = [arg.kind for arg in args]
        arg_names = [arg.variable.name() for arg in args]  # type: List[Optional[str]]
        arg_names = [None if argument_elide_name(name) else name for name in arg_names]
        if special_function_elide_names(n.name):
            arg_names = [None] * len(arg_names)

        arg_types = None  # type: List[Type]
        if (n.decorator_list and any(is_no_type_check_decorator(d) for d in n.decorator_list)):
            arg_types = [None] * len(args)
            return_type = None
        elif n.type_comment is not None and len(n.type_comment) > 0:
            try:
                func_type_ast = ast35.parse(n.type_comment, '<func_type>', 'func_type')
                assert isinstance(func_type_ast, ast35.FunctionType)
                # for ellipsis arg
                if (len(func_type_ast.argtypes) == 1 and
                        isinstance(func_type_ast.argtypes[0], ast35.Ellipsis)):
                    arg_types = [a.type_annotation if a.type_annotation is not None else AnyType()
                                for a in args]
                else:
                    # PEP 484 disallows both type annotations and type comments
                    if any(a.type_annotation is not None for a in args):
                        self.fail(messages.DUPLICATE_TYPE_SIGNATURES, n.lineno, n.col_offset)
                    arg_types = [a if a is not None else AnyType() for
                                a in converter.translate_expr_list(func_type_ast.argtypes)]
                return_type = converter.visit(func_type_ast.returns)

                # add implicit self type
                if self.in_class() and len(arg_types) < len(args):
                    arg_types.insert(0, AnyType())
            except SyntaxError:
                self.fail(TYPE_COMMENT_SYNTAX_ERROR, n.lineno, n.col_offset)
                arg_types = [AnyType()] * len(args)
                return_type = AnyType()
        else:
            arg_types = [a.type_annotation for a in args]
            return_type = converter.visit(None)

        for arg, arg_type in zip(args, arg_types):
            self.set_type_optional(arg_type, arg.initializer)

        if isinstance(return_type, UnboundType):
            return_type.is_ret_type = True

        func_type = None
        if any(arg_types) or return_type:
            if len(arg_types) != 1 and any(isinstance(t, EllipsisType) for t in arg_types):
                self.fail("Ellipses cannot accompany other argument types "
                          "in function type signature.", n.lineno, 0)
            elif len(arg_types) > len(arg_kinds):
                self.fail('Type signature has too many arguments', n.lineno, 0)
            elif len(arg_types) < len(arg_kinds):
                self.fail('Type signature has too few arguments', n.lineno, 0)
            else:
                func_type = CallableType([a if a is not None else AnyType() for a in arg_types],
                                        arg_kinds,
                                        arg_names,
                                        return_type if return_type is not None else AnyType(),
                                        None)

        body = self.as_block(n.body, n.lineno)
        if decompose_stmts:
            body.body = decompose_stmts + body.body
        func_def = FuncDef(n.name,
                       args,
                       body,
                       func_type)
        if func_type is not None:
            func_type.definition = func_def
            func_type.line = n.lineno

        if n.decorator_list:
            var = Var(func_def.name())
            var.is_ready = False
            var.set_line(n.decorator_list[0].lineno)

            func_def.is_decorated = True
            func_def.set_line(n.lineno + len(n.decorator_list))
            func_def.body.set_line(func_def.get_line())
            return Decorator(func_def, self.translate_expr_list(n.decorator_list), var)
        else:
            return func_def