Beispiel #1
0
 def analyze_callable_args(self, arglist: TypeList) -> Optional[Tuple[List[Type],
                                                                      List[int],
                                                                      List[Optional[str]]]]:
     args = []   # type: List[Type]
     kinds = []  # type: List[int]
     names = []  # type: List[str]
     for arg in arglist.items:
         if isinstance(arg, CallableArgument):
             args.append(arg.typ)
             names.append(arg.name)
             if arg.constructor is None:
                 return None
             found = self.lookup(arg.constructor, arg)
             if found is None:
                 # Looking it up already put an error message in
                 return None
             elif found.fullname not in ARG_KINDS_BY_CONSTRUCTOR:
                 self.fail('Invalid argument constructor "{}"'.format(
                     found.fullname), arg)
                 return None
             else:
                 kind = ARG_KINDS_BY_CONSTRUCTOR[found.fullname]
                 kinds.append(kind)
                 if arg.name is not None and kind in {ARG_STAR, ARG_STAR2}:
                     self.fail("{} arguments should not have names".format(
                         arg.constructor), arg)
                     return None
         else:
             args.append(arg)
             kinds.append(ARG_POS)
             names.append(None)
     # Note that arglist below is only used for error context.
     check_arg_names(names, [arglist] * len(args), self.fail, "Callable")
     check_arg_kinds(kinds, [arglist] * len(args), self.fail)
     return args, kinds, names
Beispiel #2
0
    def transform_args(
        self,
        args: ast3.arguments,
        line: int,
        no_type_check: bool = False,
    ) -> List[Argument]:
        def make_argument(arg: ast3.arg, default: Optional[ast3.expr],
                          kind: int) -> Argument:
            if no_type_check:
                arg_type = None
            else:
                if arg.annotation is not None and arg.type_comment is not None:
                    self.fail(messages.DUPLICATE_TYPE_SIGNATURES, arg.lineno,
                              arg.col_offset)
                arg_type = None
                if arg.annotation is not None:
                    arg_type = TypeConverter(
                        self.errors, line=arg.lineno).visit(arg.annotation)
                elif arg.type_comment is not None:
                    arg_type = parse_type_comment(arg.type_comment, arg.lineno,
                                                  self.errors)
            return Argument(Var(arg.arg), arg_type, self.visit(default), kind)

        new_args = []
        names = []  # type: List[ast3.arg]
        num_no_defaults = len(args.args) - len(args.defaults)
        # positional arguments without defaults
        for a in args.args[:num_no_defaults]:
            new_args.append(make_argument(a, None, ARG_POS))
            names.append(a)

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

        # *arg
        if args.vararg is not None:
            new_args.append(make_argument(args.vararg, None, ARG_STAR))
            names.append(args.vararg)

        # keyword-only arguments with defaults
        for a, d in zip(args.kwonlyargs, args.kw_defaults):
            new_args.append(
                make_argument(a, d, ARG_NAMED if d is None else ARG_NAMED_OPT))
            names.append(a)

        # **kwarg
        if args.kwarg is not None:
            new_args.append(make_argument(args.kwarg, None, ARG_STAR2))
            names.append(args.kwarg)

        def fail_arg(msg: str, arg: ast3.arg) -> None:
            self.fail(msg, arg.lineno, arg.col_offset)

        check_arg_names([name.arg for name in names], names, fail_arg)

        return new_args
Beispiel #3
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
Beispiel #4
0
    def transform_args(self,
                       args: ast3.arguments,
                       line: int,
                       no_type_check: bool = False,
                       ) -> List[Argument]:
        def make_argument(arg: ast3.arg, default: Optional[ast3.expr], kind: int) -> Argument:
            if no_type_check:
                arg_type = None
            else:
                if arg.annotation is not None and arg.type_comment is not None:
                    self.fail(messages.DUPLICATE_TYPE_SIGNATURES, arg.lineno, arg.col_offset)
                arg_type = None
                if arg.annotation is not None:
                    arg_type = TypeConverter(self.errors, line=arg.lineno).visit(arg.annotation)
                elif arg.type_comment is not None:
                    arg_type = parse_type_comment(arg.type_comment, arg.lineno, self.errors)
            return Argument(Var(arg.arg), arg_type, self.visit(default), kind)

        new_args = []
        names = []  # type: List[ast3.arg]
        num_no_defaults = len(args.args) - len(args.defaults)
        # positional arguments without defaults
        for a in args.args[:num_no_defaults]:
            new_args.append(make_argument(a, None, ARG_POS))
            names.append(a)

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

        # *arg
        if args.vararg is not None:
            new_args.append(make_argument(args.vararg, None, ARG_STAR))
            names.append(args.vararg)

        # keyword-only arguments with defaults
        for a, d in zip(args.kwonlyargs, args.kw_defaults):
            new_args.append(make_argument(
                a,
                d,
                ARG_NAMED if d is None else ARG_NAMED_OPT))
            names.append(a)

        # **kwarg
        if args.kwarg is not None:
            new_args.append(make_argument(args.kwarg, None, ARG_STAR2))
            names.append(args.kwarg)

        def fail_arg(msg: str, arg: ast3.arg) -> None:
            self.fail(msg, arg.lineno, arg.col_offset)

        check_arg_names([name.arg for name in names], names, fail_arg)

        return new_args
Beispiel #5
0
    def transform_args(self,
                       n: ast27.arguments,
                       line: int,
                       ) -> Tuple[List[Argument], List[Statement]]:
        type_comments = n.type_comments  # type: Sequence[Optional[str]]
        converter = TypeConverter(self.errors, line=line,
                                  assume_str_is_unicode=self.unicode_literals)
        decompose_stmts = []  # type: 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 = [name for arg in n_args for name in self.extract_names(arg)]  # type: List[str]

        new_args = []  # type: 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)

        # 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
Beispiel #6
0
    def transform_args(
        self,
        args: ast3.arguments,
        line: int,
        no_type_check: bool = False,
    ) -> List[Argument]:
        new_args = []
        names = []  # type: List[ast3.arg]
        args_args = args.args
        args_defaults = args.defaults
        num_no_defaults = len(args_args) - len(args_defaults)
        # positional arguments without defaults
        for a in args_args[:num_no_defaults]:
            new_args.append(self.make_argument(a, None, ARG_POS,
                                               no_type_check))
            names.append(a)

        # positional arguments with defaults
        for a, d in zip(args_args[num_no_defaults:], args_defaults):
            new_args.append(self.make_argument(a, d, ARG_OPT, no_type_check))
            names.append(a)

        # *arg
        if args.vararg is not None:
            new_args.append(
                self.make_argument(args.vararg, None, ARG_STAR, no_type_check))
            names.append(args.vararg)

        # keyword-only arguments with defaults
        for a, d in zip(args.kwonlyargs, args.kw_defaults):
            new_args.append(
                self.make_argument(a, d,
                                   ARG_NAMED if d is None else ARG_NAMED_OPT,
                                   no_type_check))
            names.append(a)

        # **kwarg
        if args.kwarg is not None:
            new_args.append(
                self.make_argument(args.kwarg, None, ARG_STAR2, no_type_check))
            names.append(args.kwarg)

        check_arg_names([arg.variable.name() for arg in new_args], names,
                        self.fail_arg)

        return new_args
Beispiel #7
0
 def analyze_callable_args(self, arglist: TypeList) -> Optional[Tuple[List[Type],
                                                                      List[int],
                                                                      List[Optional[str]]]]:
     args = []   # type: List[Type]
     kinds = []  # type: List[int]
     names = []  # type: List[Optional[str]]
     for arg in arglist.items:
         if isinstance(arg, CallableArgument):
             args.append(arg.typ)
             names.append(arg.name)
             if arg.constructor is None:
                 return None
             found = self.lookup(arg.constructor, arg)
             if found is None:
                 # Looking it up already put an error message in
                 return None
             elif found.fullname not in ARG_KINDS_BY_CONSTRUCTOR:
                 self.fail('Invalid argument constructor "{}"'.format(
                     found.fullname), arg)
                 return None
             else:
                 assert found.fullname is not None
                 kind = ARG_KINDS_BY_CONSTRUCTOR[found.fullname]
                 kinds.append(kind)
                 if arg.name is not None and kind in {ARG_STAR, ARG_STAR2}:
                     self.fail("{} arguments should not have names".format(
                         arg.constructor), arg)
                     return None
         else:
             args.append(arg)
             kinds.append(ARG_POS)
             names.append(None)
     # Note that arglist below is only used for error context.
     check_arg_names(names, [arglist] * len(args), self.fail, "Callable")
     check_arg_kinds(kinds, [arglist] * len(args), self.fail)
     return args, kinds, names
Beispiel #8
0
    def transform_args(self,
                       n: ast27.arguments,
                       line: int,
                       ) -> Tuple[List[Argument], List[Statement]]:
        type_comments = n.type_comments
        converter = TypeConverter(self.errors, line=line)
        decompose_stmts = []  # type: List[Statement]

        def extract_names(arg: ast27.expr) -> List[str]:
            if isinstance(arg, ast27.Name):
                return [arg.id]
            elif isinstance(arg, ast27.Tuple):
                return [name for elt in arg.elts for name in extract_names(elt)]
            else:
                return []

        def convert_arg(index: int, arg: ast27.expr) -> Var:
            if isinstance(arg, ast27.Name):
                v = arg.id
            elif isinstance(arg, ast27.Tuple):
                v = '__tuple_arg_{}'.format(index + 1)
                rvalue = NameExpr(v)
                rvalue.set_line(line)
                assignment = AssignmentStmt([self.visit(arg)], rvalue)
                assignment.set_line(line)
                decompose_stmts.append(assignment)
            else:
                raise RuntimeError("'{}' is not a valid argument.".format(ast27.dump(arg)))
            return Var(v)

        def get_type(i: int) -> Optional[Type]:
            if i < len(type_comments) and type_comments[i] is not None:
                return converter.visit_raw_str(type_comments[i])
            return None

        args = [(convert_arg(i, arg), get_type(i)) for i, arg in enumerate(n.args)]
        defaults = self.translate_expr_list(n.defaults)
        names = [name for arg in n.args for name in extract_names(arg)]  # type: List[str]

        new_args = []  # type: 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), get_type(len(args)), None, ARG_STAR))
            names.append(n.vararg)

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

        # 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
Beispiel #9
0
    def analyze_callable_type(self, t: UnboundType) -> Type:
        fallback = self.builtin_type('builtins.function')
        if len(t.args) == 0:
            # Callable (bare). Treat as Callable[..., Any].
            ret = CallableType([AnyType(), AnyType()],
                               [nodes.ARG_STAR, nodes.ARG_STAR2], [None, None],
                               ret_type=AnyType(),
                               fallback=fallback,
                               is_ellipsis_args=True)
        elif len(t.args) == 2:
            ret_type = t.args[1]
            if isinstance(t.args[0], TypeList):
                # Callable[[ARG, ...], RET] (ordinary callable type)
                args = []  # type: List[Type]
                names = []  # type: List[str]
                kinds = []  # type: List[int]
                for arg in t.args[0].items:
                    if isinstance(arg, CallableArgument):
                        args.append(arg.typ)
                        names.append(arg.name)
                        if arg.constructor is None:
                            return AnyType()
                        found = self.lookup(arg.constructor, arg)
                        if found is None:
                            # Looking it up already put an error message in
                            return AnyType()
                        elif found.fullname not in ARG_KINDS_BY_CONSTRUCTOR:
                            self.fail(
                                'Invalid argument constructor "{}"'.format(
                                    found.fullname), arg)
                            return AnyType()
                        else:
                            kind = ARG_KINDS_BY_CONSTRUCTOR[found.fullname]
                            kinds.append(kind)
                            if arg.name is not None and kind in {
                                    ARG_STAR, ARG_STAR2
                            }:
                                self.fail(
                                    "{} arguments should not have names".
                                    format(arg.constructor), arg)
                                return AnyType()
                    else:
                        args.append(arg)
                        names.append(None)
                        kinds.append(ARG_POS)

                check_arg_names(names, [t] * len(args), self.fail, "Callable")
                check_arg_kinds(kinds, [t] * len(args), self.fail)
                ret = CallableType(args,
                                   kinds,
                                   names,
                                   ret_type=ret_type,
                                   fallback=fallback)
            elif isinstance(t.args[0], EllipsisType):
                # Callable[..., RET] (with literal ellipsis; accept arbitrary arguments)
                ret = CallableType([AnyType(), AnyType()],
                                   [nodes.ARG_STAR, nodes.ARG_STAR2],
                                   [None, None],
                                   ret_type=ret_type,
                                   fallback=fallback,
                                   is_ellipsis_args=True)
            else:
                self.fail(
                    'The first argument to Callable must be a list of types or "..."',
                    t)
                return AnyType()
        else:
            self.fail('Invalid function type', t)
            return AnyType()
        assert isinstance(ret, CallableType)
        return ret.accept(self)
Beispiel #10
0
    def transform_args(self,
                       n: ast27.arguments,
                       line: int,
                       ) -> Tuple[List[Argument], List[Statement]]:
        type_comments = n.type_comments
        converter = TypeConverter(self.errors, line=line)
        decompose_stmts = []  # type: List[Statement]

        def extract_names(arg: ast27.expr) -> List[str]:
            if isinstance(arg, ast27.Name):
                return [arg.id]
            elif isinstance(arg, ast27.Tuple):
                return [name for elt in arg.elts for name in extract_names(elt)]
            else:
                return []

        def convert_arg(index: int, arg: ast27.expr) -> Var:
            if isinstance(arg, ast27.Name):
                v = arg.id
            elif isinstance(arg, ast27.Tuple):
                v = '__tuple_arg_{}'.format(index + 1)
                rvalue = NameExpr(v)
                rvalue.set_line(line)
                assignment = AssignmentStmt([self.visit(arg)], rvalue)
                assignment.set_line(line)
                decompose_stmts.append(assignment)
            else:
                raise RuntimeError("'{}' is not a valid argument.".format(ast27.dump(arg)))
            return Var(v)

        def get_type(i: int) -> Optional[Type]:
            if i < len(type_comments) and type_comments[i] is not None:
                return converter.visit_raw_str(type_comments[i])
            return None

        args = [(convert_arg(i, arg), get_type(i)) for i, arg in enumerate(n.args)]
        defaults = self.translate_expr_list(n.defaults)
        names = [name for arg in n.args for name in extract_names(arg)]  # type: List[str]

        new_args = []  # type: 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), get_type(len(args)), None, ARG_STAR))
            names.append(n.vararg)

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

        # 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