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