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
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
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
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
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
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
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
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
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)