Beispiel #1
0
def is_callable_subtype(left: CallableType, right: CallableType, ignore_return: bool = False) -> bool:
    """Is left a subtype of right?"""
    # TODO: Support named arguments, **args, etc.
    # Non-type cannot be a subtype of type.
    if right.is_type_obj() and not left.is_type_obj():
        return False
    if right.variables:
        # Subtyping is not currently supported for generic function as the supertype.
        return False
    if left.variables:
        # Apply generic type variables away in left via type inference.
        left = unify_generic_callable(left, right)
        if left is None:
            return False

    # Check return types.
    if not ignore_return and not is_subtype(left.ret_type, right.ret_type):
        return False

    # Check argument types.
    if left.min_args > right.min_args:
        return False
    if left.is_var_arg:
        return is_var_arg_callable_subtype_helper(left, right)
    if right.is_var_arg:
        return False
    if len(left.arg_types) < len(right.arg_types):
        return False
    for i in range(len(right.arg_types)):
        if not is_subtype(right.arg_types[i], left.arg_types[i]):
            return False
    return True
Beispiel #2
0
    def add_method(self,
                   method_name: str, args: List[Argument], ret_type: Type,
                   self_type: Optional[Type] = None,
                   tvd: Optional[TypeVarDef] = None) -> None:
        """Add a method: def <method_name>(self, <args>) -> <ret_type>): ... to info.

        self_type: The type to use for the self argument or None to use the inferred self type.
        tvd: If the method is generic these should be the type variables.
        """
        from mypy.semanal import set_callable_name
        self_type = self_type if self_type is not None else self.self_type
        args = [Argument(Var('self'), self_type, None, ARG_POS)] + args
        arg_types = [arg.type_annotation for arg in args]
        arg_names = [arg.variable.name() for arg in args]
        arg_kinds = [arg.kind for arg in args]
        assert None not in arg_types
        signature = CallableType(cast(List[Type], arg_types), arg_kinds, arg_names,
                                 ret_type, self.function_type)
        if tvd:
            signature.variables = [tvd]
        func = FuncDef(method_name, args, Block([PassStmt()]))
        func.info = self.info
        func.type = set_callable_name(signature, func)
        func._fullname = self.info.fullname() + '.' + method_name
        func.line = self.info.line
        self.info.names[method_name] = SymbolTableNode(MDEF, func)
        # Add the created methods to the body so that they can get further semantic analysis.
        # e.g. Forward Reference Resolution.
        self.info.defn.defs.body.append(func)
Beispiel #3
0
def add_method(
        ctx: ClassDefContext,
        name: str,
        args: List[Argument],
        return_type: Type,
        self_type: Optional[Type] = None,
        tvar_def: Optional[TypeVarDef] = None,
) -> None:
    """Adds a new method to a class.
    """
    info = ctx.cls.info
    self_type = self_type or fill_typevars(info)
    function_type = ctx.api.named_type('__builtins__.function')

    args = [Argument(Var('self'), self_type, None, ARG_POS)] + args
    arg_types, arg_names, arg_kinds = [], [], []
    for arg in args:
        assert arg.type_annotation, 'All arguments must be fully typed.'
        arg_types.append(arg.type_annotation)
        arg_names.append(arg.variable.name())
        arg_kinds.append(arg.kind)

    signature = CallableType(arg_types, arg_kinds, arg_names, return_type, function_type)
    if tvar_def:
        signature.variables = [tvar_def]

    func = FuncDef(name, args, Block([PassStmt()]))
    func.info = info
    func.type = set_callable_name(signature, func)
    func._fullname = info.fullname() + '.' + name
    func.line = info.line

    info.names[name] = SymbolTableNode(MDEF, func, plugin_generated=True)
    info.defn.defs.body.append(func)
Beispiel #4
0
        def add_method(funcname: str,
                       ret: Type,
                       args: List[Argument],
                       name: Optional[str] = None,
                       is_classmethod: bool = False,
                       is_new: bool = False,
                       ) -> None:
            if is_classmethod or is_new:
                first = [Argument(Var('cls'), TypeType.make_normalized(selftype), None, ARG_POS)]
            else:
                first = [Argument(Var('self'), selftype, None, ARG_POS)]
            args = first + args

            types = [arg.type_annotation for arg in args]
            items = [arg.variable.name() for arg in args]
            arg_kinds = [arg.kind for arg in args]
            assert None not in types
            signature = CallableType(cast(List[Type], types), arg_kinds, items, ret,
                                     function_type)
            signature.variables = [tvd]
            func = FuncDef(funcname, args, Block([]))
            func.info = info
            func.is_class = is_classmethod
            func.type = set_callable_name(signature, func)
            func._fullname = info.fullname() + '.' + funcname
            if is_classmethod:
                v = Var(funcname, func.type)
                v.is_classmethod = True
                v.info = info
                v._fullname = func._fullname
                dec = Decorator(func, [NameExpr('classmethod')], v)
                info.names[funcname] = SymbolTableNode(MDEF, dec)
            else:
                info.names[funcname] = SymbolTableNode(MDEF, func)
Beispiel #5
0
    def visit_FunctionDef(self, n: ast35.FunctionDef) -> Node:
        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]
        arg_types = None  # type: List[Type]
        if n.type_comment is not None:
            try:
                func_type_ast = ast35.parse(n.type_comment, '<func_type>', 'func_type')
            except SyntaxError:
                raise TypeCommentParseError(TYPE_COMMENT_SYNTAX_ERROR, n.lineno)
            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 TypeConverter(line=n.lineno).visit_list(func_type_ast.argtypes)]
            return_type = TypeConverter(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())
        else:
            arg_types = [a.type_annotation for a in args]
            return_type = TypeConverter(line=n.lineno).visit(n.returns)

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

        func_type = None
        if any(arg_types) or return_type:
            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.visit_list(n.decorator_list), var)
        else:
            return func_def
Beispiel #6
0
 def visit_callable_type(self, t: CallableType) -> Type:
     if isinstance(self.s, CallableType) and is_similar_callables(
             t, cast(CallableType, self.s)):
         return combine_similar_callables(t, cast(CallableType, self.s))
     elif t.is_type_obj() and is_subtype(self.s, t.fallback):
         return t.fallback
     elif (t.is_type_obj() and isinstance(self.s, Instance) and
           cast(Instance, self.s).type == t.fallback):
         return t.fallback
     else:
         return self.default(self.s)
Beispiel #7
0
def infer_function_type_arguments(callee_type: CallableType,
                                  arg_types: List[Optional[Type]],
                                  arg_kinds: List[int],
                                  formal_to_actual: List[List[int]],
                                  strict: bool = True) -> List[Type]:
    """Infer the type arguments of a generic function.

    Return an array of lower bound types for the type variables -1 (at
    index 0), -2 (at index 1), etc. A lower bound is None if a value
    could not be inferred.

    Arguments:
      callee_type: the target generic function
      arg_types: argument types at the call site (each optional; if None,
                 we are not considering this argument in the current pass)
      arg_kinds: nodes.ARG_* values for arg_types
      formal_to_actual: mapping from formal to actual variable indices
    """
    # Infer constraints.
    constraints = infer_constraints_for_callable(
        callee_type, arg_types, arg_kinds, formal_to_actual)

    # Solve constraints.
    type_vars = callee_type.type_var_ids()
    return solve_constraints(type_vars, constraints, strict)
Beispiel #8
0
 def visit_callable_type(self, t: CallableType) -> Type:
     return t.copy_modified(
         arg_types=self.anal_array(t.arg_types),
         ret_type=t.ret_type.accept(self),
         fallback=t.fallback or self.builtin_type("builtins.function"),
         variables=self.anal_var_defs(t.variables),
     )
Beispiel #9
0
    def get_guesses(self, is_method: bool, base: CallableType, defaults: List[Optional[Type]],
                    callsites: List[Callsite]) -> List[CallableType]:
        """Compute a list of guesses for a function's type.

        This focuses just on the argument types, and doesn't change the provided return type.
        """
        options = self.get_args(is_method, base, defaults, callsites)
        return [base.copy_modified(arg_types=list(x)) for x in itertools.product(*options)]
Beispiel #10
0
def is_callable_subtype(left: CallableType, right: CallableType,
                        ignore_return: bool = False) -> bool:
    """Is left a subtype of right?"""
    # TODO: Support named arguments, **args, etc.
    # Non-type cannot be a subtype of type.
    if right.is_type_obj() and not left.is_type_obj():
        return False

    # A callable L is a subtype of a generic callable R if L is a
    # subtype of every type obtained from R by substituting types for
    # the variables of R. We can check this by simply leaving the
    # generic variables of R as type variables, effectively varying
    # over all possible values.

    # It's okay even if these variables share ids with generic
    # type variables of L, because generating and solving
    # constraints for the variables of L to make L a subtype of R
    # (below) treats type variables on the two sides as independent.

    if left.variables:
        # Apply generic type variables away in left via type inference.
        left = unify_generic_callable(left, right, ignore_return=ignore_return)
        if left is None:
            return False

    # Check return types.
    if not ignore_return and not is_subtype(left.ret_type, right.ret_type):
        return False

    if right.is_ellipsis_args:
        return True

    # Check argument types.
    if left.min_args > right.min_args:
        return False
    if left.is_var_arg:
        return is_var_arg_callable_subtype_helper(left, right)
    if right.is_var_arg:
        return False
    if len(left.arg_types) < len(right.arg_types):
        return False
    for i in range(len(right.arg_types)):
        if not is_subtype(right.arg_types[i], left.arg_types[i]):
            return False
    return True
Beispiel #11
0
 def visit_callable_type(self, typ: CallableType) -> SnapshotItem:
     # FIX generics
     return ('CallableType',
             snapshot_types(typ.arg_types),
             snapshot_type(typ.ret_type),
             tuple(typ.arg_names),
             tuple(typ.arg_kinds),
             typ.is_type_obj(),
             typ.is_ellipsis_args)
Beispiel #12
0
    def visit_FunctionDef(self, n):
        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]
        if n.type_comment is not None:
            func_type_ast = typed_ast.parse(n.type_comment, '<func_type>', 'func_type')
            arg_types = [a if a is not None else AnyType() for
                         a in TypeConverter(line=n.lineno).visit(func_type_ast.argtypes)]
            return_type = TypeConverter(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())
        else:
            arg_types = [a.type_annotation for a in args]
            return_type = TypeConverter(line=n.lineno).visit(n.returns)

        func_type = None
        if any(arg_types) or return_type:
            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

        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.visit(n.decorator_list), var)
        else:
            return func_def
Beispiel #13
0
def apply_generic_arguments(callable: CallableType, types: List[Type],
                            msg: MessageBuilder, context: Context) -> Type:
    """Apply generic type arguments to a callable type.

    For example, applying [int] to 'def [T] (T) -> T' results in
    'def (int) -> int'.

    Note that each type can be None; in this case, it will not be applied.
    """
    tvars = callable.variables
    if len(tvars) != len(types):
        msg.incompatible_type_application(len(tvars), len(types), context)
        return AnyType()

    # Check that inferred type variable values are compatible with allowed
    # values and bounds.  Also, promote subtype values to allowed values.
    types = types[:]
    for i, type in enumerate(types):
        values = callable.variables[i].values
        if values and type:
            if isinstance(type, AnyType):
                continue
            if isinstance(type, TypeVarType) and type.values:
                # Allow substituting T1 for T if every allowed value of T1
                # is also a legal value of T.
                if all(any(is_same_type(v, v1) for v in values)
                       for v1 in type.values):
                    continue
            for value in values:
                if mypy.subtypes.is_subtype(type, value):
                    types[i] = value
                    break
            else:
                msg.incompatible_typevar_value(callable, i + 1, type, context)

        upper_bound = callable.variables[i].upper_bound
        if type and not mypy.subtypes.satisfies_upper_bound(type, upper_bound):
            msg.incompatible_typevar_value(callable, i + 1, type, context)

    # Create a map from type variable id to target type.
    id_to_type = {}  # type: Dict[TypeVarId, Type]
    for i, tv in enumerate(tvars):
        if types[i]:
            id_to_type[tv.id] = types[i]

    # Apply arguments to argument types.
    arg_types = [expand_type(at, id_to_type) for at in callable.arg_types]

    # The callable may retain some type vars if only some were applied.
    remaining_tvars = [tv for tv in tvars if tv.id not in id_to_type]

    return callable.copy_modified(
        arg_types=arg_types,
        ret_type=expand_type(callable.ret_type, id_to_type),
        variables=remaining_tvars,
    )
Beispiel #14
0
 def analyze_callable_type(self, t: UnboundType) -> Type:
     fallback = self.named_type('builtins.function')
     if len(t.args) == 0:
         # Callable (bare). Treat as Callable[..., Any].
         any_type = AnyType(TypeOfAny.from_omitted_generics,
                            line=t.line, column=t.column)
         ret = CallableType([any_type, any_type],
                            [nodes.ARG_STAR, nodes.ARG_STAR2],
                            [None, None],
                            ret_type=any_type,
                            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)
             analyzed_args = self.analyze_callable_args(t.args[0])
             if analyzed_args is None:
                 return AnyType(TypeOfAny.from_error)
             args, kinds, names = analyzed_args
             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(TypeOfAny.explicit),
                                 AnyType(TypeOfAny.explicit)],
                                [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(TypeOfAny.from_error)
     else:
         self.fail('Please use "Callable[[<parameters>], <return type>]" or "Callable"', t)
         return AnyType(TypeOfAny.from_error)
     assert isinstance(ret, CallableType)
     return ret.accept(self)
Beispiel #15
0
 def visit_callable_type(self, left: CallableType) -> bool:
     # FIX generics
     if isinstance(self.right, CallableType):
         cright = cast(CallableType, self.right)
         return (is_same_type(left.ret_type, cright.ret_type) and
                 is_same_types(left.arg_types, cright.arg_types) and
                 left.arg_names == cright.arg_names and
                 left.arg_kinds == cright.arg_kinds and
                 left.is_type_obj() == cright.is_type_obj())
     else:
         return False
Beispiel #16
0
 def visit_callable_type(self, left: CallableType) -> bool:
     # FIX generics
     if isinstance(self.right, CallableType):
         cright = self.right
         return (is_identical_type(left.ret_type, cright.ret_type) and
                 is_identical_types(left.arg_types, cright.arg_types) and
                 left.arg_names == cright.arg_names and
                 left.arg_kinds == cright.arg_kinds and
                 left.is_type_obj() == cright.is_type_obj() and
                 left.is_ellipsis_args == cright.is_ellipsis_args)
     return False
Beispiel #17
0
 def visit_callable_type(self, t: CallableType) -> Type:
     if isinstance(self.s, CallableType) and is_similar_callables(t, self.s):
         if is_equivalent(t, self.s):
             return combine_similar_callables(t, self.s)
         result = meet_similar_callables(t, self.s)
         if isinstance(result.ret_type, UninhabitedType):
             # Return a plain None or <uninhabited> instead of a weird function.
             return self.default(self.s)
         return result
     elif isinstance(self.s, TypeType) and t.is_type_obj() and not t.is_generic():
         # In this case we are able to potentially produce a better meet.
         res = meet_types(self.s.item, t.ret_type)
         if not isinstance(res, (NoneType, UninhabitedType)):
             return TypeType.make_normalized(res)
         return self.default(self.s)
     elif isinstance(self.s, Instance) and self.s.type.is_protocol:
         call = unpack_callback_protocol(self.s)
         if call:
             return meet_types(t, call)
     return self.default(self.s)
Beispiel #18
0
 def visit_callable_type(self, t: CallableType) -> Type:
     if self.check_recursion(t):
         return AnyType(TypeOfAny.from_error)
     arg_types = [tp.accept(self) for tp in t.arg_types]
     ret_type = t.ret_type.accept(self)
     variables = t.variables.copy()
     for v in variables:
         if v.upper_bound:
             v.upper_bound = v.upper_bound.accept(self)
         if v.values:
             v.values = [val.accept(self) for val in v.values]
     return t.copy_modified(arg_types=arg_types, ret_type=ret_type, variables=variables)
Beispiel #19
0
 def visit_callable_type(self, typ: CallableType) -> None:
     for arg in typ.arg_types:
         arg.accept(self)
     typ.ret_type.accept(self)
     if typ.definition:
         # No need to fixup since this is just a cross-reference.
         typ.definition = self.replacements.get(typ.definition, typ.definition)
     # TODO: typ.fallback
     for tv in typ.variables:
         tv.upper_bound.accept(self)
         for value in tv.values:
             value.accept(self)
Beispiel #20
0
 def visit_callable_type(self, t: CallableType, nested: bool = True) -> Type:
     # Every Callable can bind its own type variables, if they're not in the outer scope
     with self.tvar_scope_frame():
         if self.aliasing:
             variables = t.variables
         else:
             variables = self.bind_function_type_variables(t, t)
         ret = t.copy_modified(arg_types=self.anal_array(t.arg_types, nested=nested),
                               ret_type=self.anal_type(t.ret_type, nested=nested),
                               fallback=t.fallback or self.named_type('builtins.function'),
                               variables=self.anal_var_defs(variables))
     return ret
Beispiel #21
0
def class_callable(init_type: CallableType, info: TypeInfo, type_type: Instance,
                   special_sig: Optional[str]) -> CallableType:
    """Create a type object type based on the signature of __init__."""
    variables = []  # type: List[TypeVarDef]
    variables.extend(info.defn.type_vars)
    variables.extend(init_type.variables)

    callable_type = init_type.copy_modified(
        ret_type=fill_typevars(info), fallback=type_type, name=None, variables=variables,
        special_sig=special_sig)
    c = callable_type.with_name(info.name())
    return c
Beispiel #22
0
def apply_generic_arguments(callable: CallableType, types: List[Type],
                            msg: MessageBuilder, context: Context) -> Type:
    """Apply generic type arguments to a callable type.

    For example, applying [int] to 'def [T] (T) -> T' results in
    'def [-1:int] (int) -> int'. Here '[-1:int]' is an implicit bound type
    variable.

    Note that each type can be None; in this case, it will not be applied.
    """
    tvars = callable.variables
    if len(tvars) != len(types):
        msg.incompatible_type_application(len(tvars), len(types), context)
        return AnyType()

    # Check that inferred type variable values are compatible with allowed
    # values.  Also, promote subtype values to allowed values.
    types = types[:]
    for i, type in enumerate(types):
        values = callable.variables[i].values
        if values and type:
            if isinstance(type, AnyType):
                continue
            for value in values:
                if mypy.subtypes.is_subtype(type, value):
                    types[i] = value
                    break
            else:
                msg.incompatible_typevar_value(callable, i + 1, type, context)

    # Create a map from type variable id to target type.
    id_to_type = {}  # type: Dict[int, Type]
    for i, tv in enumerate(tvars):
        if types[i]:
            id_to_type[tv.id] = types[i]

    # Apply arguments to argument types.
    arg_types = [expand_type(at, id_to_type) for at in callable.arg_types]

    bound_vars = [(tv.id, id_to_type[tv.id])
                  for tv in tvars
                  if tv.id in id_to_type]

    # The callable may retain some type vars if only some were applied.
    remaining_tvars = [tv for tv in tvars if tv.id not in id_to_type]

    return callable.copy_modified(
        arg_types=arg_types,
        ret_type=expand_type(callable.ret_type, id_to_type),
        variables=remaining_tvars,
        bound_vars=callable.bound_vars + bound_vars,
    )
Beispiel #23
0
 def visit_callable_type(self, left: CallableType) -> bool:
     right = self.right
     if isinstance(right, CallableType):
         return is_callable_subtype(left, right)
     elif isinstance(right, Overloaded):
         return all(is_subtype(left, item) for item in right.items())
     elif is_named_instance(right, 'builtins.object'):
         return True
     elif (is_named_instance(right, 'builtins.type') and
           left.is_type_obj()):
         return True
     else:
         return False
Beispiel #24
0
 def visit_callable_type(self, typ: CallableType) -> None:
     for arg in typ.arg_types:
         arg.accept(self)
     typ.ret_type.accept(self)
     if typ.definition:
         # No need to fixup since this is just a cross-reference.
         typ.definition = self.replacements.get(typ.definition, typ.definition)
     # Fallback can be None for callable types that haven't been semantically analyzed.
     if typ.fallback is not None:
         typ.fallback.accept(self)
     for tv in typ.variables:
         tv.upper_bound.accept(self)
         for value in tv.values:
             value.accept(self)
Beispiel #25
0
def class_callable(init_type: CallableType, info: TypeInfo, type_type: Instance) -> CallableType:
    """Create a type object type based on the signature of __init__."""
    variables = []  # type: List[TypeVarDef]
    for i, tvar in enumerate(info.defn.type_vars):
        variables.append(TypeVarDef(tvar.name, i + 1, tvar.values, tvar.upper_bound,
                                    tvar.variance))

    initvars = init_type.variables
    variables.extend(initvars)

    callable_type = init_type.copy_modified(
        ret_type=self_type(info), fallback=type_type, name=None, variables=variables)
    c = callable_type.with_name('"{}"'.format(info.name()))
    return convert_class_tvars_to_func_tvars(c, len(initvars))
Beispiel #26
0
 def visit_callable_type(self, left: CallableType) -> bool:
     right = self.right
     if isinstance(right, CallableType):
         return is_callable_subtype(left, right)
     elif isinstance(right, Overloaded):
         return all(is_subtype(left, item, self.check_type_parameter)
                    for item in right.items())
     elif isinstance(right, Instance):
         return is_subtype(left.fallback, right)
     elif isinstance(right, TypeType):
         # This is unsound, we don't check the __init__ signature.
         return left.is_type_obj() and is_subtype(left.ret_type, right.item)
     else:
         return False
Beispiel #27
0
def is_var_arg_callable_subtype_helper(left: CallableType, right: CallableType) -> bool:
    """Is left a subtype of right, assuming left has *args?

    See also is_callable_subtype for additional assumptions we can make.
    """
    left_fixed = left.max_fixed_args()
    right_fixed = right.max_fixed_args()
    num_fixed_matching = min(left_fixed, right_fixed)
    for i in range(num_fixed_matching):
        if not is_subtype(right.arg_types[i], left.arg_types[i]):
            return False
    if not right.is_var_arg:
        for i in range(num_fixed_matching, len(right.arg_types)):
            if not is_subtype(right.arg_types[i], left.arg_types[-1]):
                return False
        return True
    else:
        for i in range(left_fixed, right_fixed):
            if not is_subtype(right.arg_types[i], left.arg_types[-1]):
                return False
        for i in range(right_fixed, left_fixed):
            if not is_subtype(right.arg_types[-1], left.arg_types[i]):
                return False
        return is_subtype(right.arg_types[-1], left.arg_types[-1])
Beispiel #28
0
def combine_similar_callables(t: CallableType, s: CallableType) -> CallableType:
    arg_types = []  # type: List[Type]
    for i in range(len(t.arg_types)):
        arg_types.append(join_types(t.arg_types[i], s.arg_types[i]))
    # TODO kinds and argument names
    # The fallback type can be either 'function' or 'type'. The result should have 'type' as
    # fallback only if both operands have it as 'type'.
    if t.fallback.type.fullname() != 'builtins.type':
        fallback = t.fallback
    else:
        fallback = s.fallback
    return t.copy_modified(arg_types=arg_types,
                           ret_type=join_types(t.ret_type, s.ret_type),
                           fallback=fallback,
                           name=None)
Beispiel #29
0
 def visit_callable_type(self, left: CallableType) -> bool:
     right = self.right
     if isinstance(right, CallableType):
         return is_callable_subtype(
             left, right,
             ignore_pos_arg_names=False,
             use_proper_subtype=True)
     elif isinstance(right, Overloaded):
         return all(is_proper_subtype(left, item)
                    for item in right.items())
     elif isinstance(right, Instance):
         return is_proper_subtype(left.fallback, right)
     elif isinstance(right, TypeType):
         # This is unsound, we don't check the __init__ signature.
         return left.is_type_obj() and is_proper_subtype(left.ret_type, right.item)
     return False
Beispiel #30
0
def meet_similar_callables(t: CallableType, s: CallableType) -> CallableType:
    from mypy.join import join_types
    arg_types = []  # type: List[Type]
    for i in range(len(t.arg_types)):
        arg_types.append(join_types(t.arg_types[i], s.arg_types[i]))
    # TODO in combine_similar_callables also applies here (names and kinds)
    # The fallback type can be either 'function' or 'type'. The result should have 'function' as
    # fallback only if both operands have it as 'function'.
    if t.fallback.type.fullname() != 'builtins.function':
        fallback = t.fallback
    else:
        fallback = s.fallback
    return t.copy_modified(arg_types=arg_types,
                           ret_type=meet_types(t.ret_type, s.ret_type),
                           fallback=fallback,
                           name=None)
Beispiel #31
0
 def visit_callable_type(self,
                         t: CallableType,
                         nested: bool = True) -> Type:
     # Every Callable can bind its own type variables, if they're not in the outer scope
     with self.tvar_scope_frame():
         if self.defining_alias:
             variables = t.variables
         else:
             variables = self.bind_function_type_variables(t, t)
         ret = t.copy_modified(
             arg_types=self.anal_array(t.arg_types, nested=nested),
             ret_type=self.anal_type(t.ret_type, nested=nested),
             # If the fallback isn't filled in yet,
             # its type will be the falsey FakeInfo
             fallback=(t.fallback if t.fallback.type else
                       self.named_type('builtins.function')),
             variables=self.anal_var_defs(variables))
     return ret
Beispiel #32
0
def join_similar_callables(t: CallableType, s: CallableType) -> CallableType:
    from mypy.meet import meet_types

    arg_types: List[Type] = []
    for i in range(len(t.arg_types)):
        arg_types.append(meet_types(t.arg_types[i], s.arg_types[i]))
    # TODO in combine_similar_callables also applies here (names and kinds)
    # The fallback type can be either 'function' or 'type'. The result should have 'type' as
    # fallback only if both operands have it as 'type'.
    if t.fallback.type.fullname != 'builtins.type':
        fallback = t.fallback
    else:
        fallback = s.fallback
    return t.copy_modified(arg_types=arg_types,
                           arg_names=combine_arg_names(t, s),
                           ret_type=join_types(t.ret_type, s.ret_type),
                           fallback=fallback,
                           name=None)
Beispiel #33
0
def analyze_none_member_access(name: str, typ: NoneType,
                               mx: MemberContext) -> Type:
    is_python_3 = mx.chk.options.python_version[0] >= 3
    # In Python 2 "None" has exactly the same attributes as "object". Python 3 adds a single
    # extra attribute, "__bool__".
    if is_python_3 and name == '__bool__':
        literal_false = LiteralType(False,
                                    fallback=mx.named_type('builtins.bool'))
        return CallableType(arg_types=[],
                            arg_kinds=[],
                            arg_names=[],
                            ret_type=literal_false,
                            fallback=mx.named_type('builtins.function'))
    elif mx.chk.should_suppress_optional_error([typ]):
        return AnyType(TypeOfAny.from_error)
    else:
        return _analyze_member_access(name, mx.named_type('builtins.object'),
                                      mx)
Beispiel #34
0
 def visit_callable_type(self, left: CallableType) -> bool:
     right = self.right
     if isinstance(right, CallableType):
         return is_callable_subtype(
             left, right,
             ignore_pos_arg_names=self.ignore_pos_arg_names)
     elif isinstance(right, Overloaded):
         return all(is_subtype(left, item, self.check_type_parameter,
                               ignore_pos_arg_names=self.ignore_pos_arg_names)
                    for item in right.items())
     elif isinstance(right, Instance):
         return is_subtype(left.fallback, right,
                           ignore_pos_arg_names=self.ignore_pos_arg_names)
     elif isinstance(right, TypeType):
         # This is unsound, we don't check the __init__ signature.
         return left.is_type_obj() and is_subtype(left.ret_type, right.item)
     else:
         return False
Beispiel #35
0
 def analyze_callable_type(self, t: UnboundType) -> Type:
     fallback = self.named_type('builtins.function')
     if len(t.args) == 0:
         # Callable (bare). Treat as Callable[..., Any].
         any_type = AnyType(TypeOfAny.from_omitted_generics,
                            line=t.line,
                            column=t.column)
         ret = CallableType([any_type, any_type],
                            [nodes.ARG_STAR, nodes.ARG_STAR2], [None, None],
                            ret_type=any_type,
                            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)
             analyzed_args = self.analyze_callable_args(t.args[0])
             if analyzed_args is None:
                 return AnyType(TypeOfAny.from_error)
             args, kinds, names = analyzed_args
             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(TypeOfAny.explicit),
                  AnyType(TypeOfAny.explicit)],
                 [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(TypeOfAny.from_error)
     else:
         self.fail(
             'Please use "Callable[[<parameters>], <return type>]" or "Callable"',
             t)
         return AnyType(TypeOfAny.from_error)
     assert isinstance(ret, CallableType)
     return ret.accept(self)
Beispiel #36
0
def combine_similar_callables(t: CallableType, s: CallableType) -> CallableType:
    arg_types = []  # type: List[Type]
    for i in range(len(t.arg_types)):
        arg_types.append(join_types(t.arg_types[i], s.arg_types[i]))
    # TODO kinds and argument names
    # The fallback type can be either 'function' or 'type'. The result should have 'type' as
    # fallback only if both operands have it as 'type'.
    if t.fallback.type.fullname() != 'builtins.type':
        fallback = t.fallback
    else:
        fallback = s.fallback
    return CallableType(arg_types,
                    t.arg_kinds,
                    t.arg_names,
                    join_types(t.ret_type, s.ret_type),
                    fallback,
                    None,
                    t.variables)
    return s
Beispiel #37
0
def class_callable(init_type: CallableType, info: TypeInfo,
                   type_type: Instance) -> CallableType:
    """Create a type object type based on the signature of __init__."""
    variables = []  # type: List[TypeVarDef]
    for i, tvar in enumerate(info.defn.type_vars):
        variables.append(
            TypeVarDef(tvar.name, i + 1, tvar.values, tvar.upper_bound,
                       tvar.variance))

    initvars = init_type.variables
    variables.extend(initvars)

    callable_type = init_type.copy_modified(ret_type=self_type(info),
                                            fallback=type_type,
                                            name=None,
                                            variables=variables)
    c = callable_type.with_name('"{}"'.format(info.name()))
    cc = convert_class_tvars_to_func_tvars(c, len(initvars))
    cc.is_classmethod_class = True
    return cc
Beispiel #38
0
def class_callable(init_type: CallableType, info: TypeInfo,
                   type_type: Instance, special_sig: Optional[str],
                   is_new: bool) -> CallableType:
    """Create a type object type based on the signature of __init__."""
    variables = []  # type: List[TypeVarDef]
    variables.extend(info.defn.type_vars)
    variables.extend(init_type.variables)

    if is_new and isinstance(init_type.ret_type, (Instance, TupleType)):
        ret_type = init_type.ret_type  # type: Type
    else:
        ret_type = fill_typevars(info)

    callable_type = init_type.copy_modified(ret_type=ret_type,
                                            fallback=type_type,
                                            name=None,
                                            variables=variables,
                                            special_sig=special_sig)
    c = callable_type.with_name(info.name())
    return c
Beispiel #39
0
    def build_newtype_typeinfo(self, name: str, old_type: Type, base_type: Instance) -> TypeInfo:
        info = self.api.basic_new_typeinfo(name, base_type)
        info.is_newtype = True

        # Add __init__ method
        args = [Argument(Var('self'), NoneType(), None, ARG_POS),
                self.make_argument('item', old_type)]
        signature = CallableType(
            arg_types=[Instance(info, []), old_type],
            arg_kinds=[arg.kind for arg in args],
            arg_names=['self', 'item'],
            ret_type=NoneType(),
            fallback=self.api.named_type('__builtins__.function'),
            name=name)
        init_func = FuncDef('__init__', args, Block([]), typ=signature)
        init_func.info = info
        init_func._fullname = info.fullname + '.__init__'
        info.names['__init__'] = SymbolTableNode(MDEF, init_func)

        return info
Beispiel #40
0
 def analyze_callable_type(self, t: UnboundType) -> Type:
     fallback = self.named_type('builtins.function')
     if len(t.args) == 0:
         # Callable (bare). Treat as Callable[..., Any].
         any_type = AnyType(TypeOfAny.from_omitted_generics,
                            line=t.line,
                            column=t.column)
         ret = CallableType([any_type, any_type],
                            [nodes.ARG_STAR, nodes.ARG_STAR2], [None, None],
                            ret_type=any_type,
                            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)
             analyzed_args = self.analyze_callable_args(t.args[0])
             if analyzed_args is None:
                 return AnyType(TypeOfAny.from_error)
             args, kinds, names = analyzed_args
             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(TypeOfAny.explicit),
                  AnyType(TypeOfAny.explicit)],
                 [nodes.ARG_STAR, nodes.ARG_STAR2], [None, None],
                 ret_type=ret_type,
                 fallback=fallback,
                 is_ellipsis_args=True)
         else:
             self.fail(errorcode.THE_FIRST_ARGUMENT_TO_CALLABLE_MUST_BE(),
                       t)
             return AnyType(TypeOfAny.from_error)
     else:
         self.fail(errorcode.USE_CALLABLE_TYPE_SYNTAX(), t)
         return AnyType(TypeOfAny.from_error)
     assert isinstance(ret, CallableType)
     return ret.accept(self)
Beispiel #41
0
def function_type(func: FuncBase, fallback: Instance) -> FunctionLike:
    if func.type:
        assert isinstance(func.type, FunctionLike)
        return func.type
    else:
        # Implicit type signature with dynamic types.
        if isinstance(func, FuncItem):
            return callable_type(func, fallback)
        else:
            # Broken overloads can have self.type set to None.
            # TODO: should we instead always set the type in semantic analyzer?
            assert isinstance(func, OverloadedFuncDef)
            any_type = AnyType(TypeOfAny.from_error)
            dummy = CallableType([any_type, any_type],
                                 [ARG_STAR, ARG_STAR2],
                                 [None, None], any_type,
                                 fallback,
                                 line=func.line, is_ellipsis_args=True)
            # Return an Overloaded, because some callers may expect that
            # an OverloadedFuncDef has an Overloaded type.
            return Overloaded([dummy])
Beispiel #42
0
def infer_function_type_arguments(
        callee_type: CallableType, arg_types: List[Type], arg_kinds: List[int],
        formal_to_actual: List[List[int]]) -> List[Type]:
    """Infer the type arguments of a generic function.

    Return an array of lower bound types for the type variables -1 (at
    index 0), -2 (at index 1), etc. A lower bound is None if a value
    could not be inferred.

    Arguments:
      callee_type: the target generic function
      arg_types: argument types at the call site
      arg_kinds: nodes.ARG_* values for arg_types
      formal_to_actual: mapping from formal to actual variable indices
    """
    # Infer constraints.
    constraints = infer_constraints_for_callable(callee_type, arg_types,
                                                 arg_kinds, formal_to_actual)

    # Solve constraints.
    type_vars = callee_type.type_var_ids()
    return solve_constraints(type_vars, constraints)
Beispiel #43
0
def type_object_type(check_untyped_defs: bool, info: TypeInfo,
                     builtin_type: Callable[[str], Instance]) -> Type:
    """Return the type of a type object.

    For a generic type G with type variables T and S the type is generally of form

      Callable[..., G[T, S]]

    where ... are argument types for the __init__/__new__ method (without the self
    argument). Also, the fallback type will be 'type' instead of 'function'.
    """
    init_method = info.get_method('__init__')
    if not init_method:
        # Must be an invalid class definition.
        return AnyType()
    else:
        fallback = builtin_type('builtins.type')
        if init_method.info.fullname() == 'builtins.object':
            # No non-default __init__ -> look at __new__ instead.
            new_method = info.get_method('__new__')
            if new_method and new_method.info.fullname() != 'builtins.object':
                # Found one! Get signature from __new__.
                return type_object_type_from_function(check_untyped_defs,
                                                      new_method, info,
                                                      fallback)
            # Both are defined by object.  But if we've got a bogus
            # base class, we can't know for sure, so check for that.
            if info.fallback_to_any:
                # Construct a universal callable as the prototype.
                sig = CallableType(arg_types=[AnyType(), AnyType()],
                                   arg_kinds=[ARG_STAR, ARG_STAR2],
                                   arg_names=["_args", "_kwds"],
                                   ret_type=AnyType(),
                                   fallback=builtin_type('builtins.function'))
                return class_callable(sig, info, fallback, None)
        # Construct callable type based on signature of __init__. Adjust
        # return type and insert type arguments.
        return type_object_type_from_function(check_untyped_defs, init_method,
                                              info, fallback)
Beispiel #44
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,
    )
Beispiel #45
0
def class_callable(init_type: CallableType,
                   info: TypeInfo,
                   type_type: Instance,
                   special_sig: Optional[str],
                   is_new: bool,
                   orig_self_type: Optional[Type] = None) -> CallableType:
    """Create a type object type based on the signature of __init__."""
    variables: List[TypeVarLikeType] = []
    variables.extend(info.defn.type_vars)
    variables.extend(init_type.variables)

    from mypy.subtypes import is_subtype

    init_ret_type = get_proper_type(init_type.ret_type)
    orig_self_type = get_proper_type(orig_self_type)
    default_ret_type = fill_typevars(info)
    explicit_type = init_ret_type if is_new else orig_self_type
    if (isinstance(explicit_type, (Instance, TupleType))
            # We have to skip protocols, because it can can be a subtype of a return type
            # by accident. Like `Hashable` is a subtype of `object`. See #11799
            and isinstance(default_ret_type, Instance) and
            not default_ret_type.type.is_protocol
            # Only use the declared return type from __new__ or declared self in __init__
            # if it is actually returning a subtype of what we would return otherwise.
            and is_subtype(
                explicit_type, default_ret_type, ignore_type_params=True)):
        ret_type: Type = explicit_type
    else:
        ret_type = default_ret_type

    callable_type = init_type.copy_modified(ret_type=ret_type,
                                            fallback=type_type,
                                            name=None,
                                            variables=variables,
                                            special_sig=special_sig)
    c = callable_type.with_name(info.name)
    return c
Beispiel #46
0
 def analyze_callable_type(self, t: UnboundType) -> Type:
     fallback = self.named_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)
             analyzed_args = self.analyze_callable_args(t.args[0])
             if analyzed_args is None:
                 return AnyType()
             args, kinds, names = analyzed_args
             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 #47
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: Type = fill_typevars(fdef.info)
        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,
        fdef.arg_names,
        ret_type or AnyType(TypeOfAny.unannotated),
        fallback,
        name=fdef.name,
        line=fdef.line,
        column=fdef.column,
        implicit=True,
        # We need this for better error messages, like missing `self` note:
        definition=fdef if isinstance(fdef, FuncDef) else None,
    )
Beispiel #48
0
def parse_signature(tokens: List[Token]) -> Tuple[CallableType, int]:
    """Parse signature of form (argtype, ...) -> ...

    Return tuple (signature type, token index).
    """
    i = 0
    if tokens[i].string != '(':
        raise TypeParseError(tokens[i], i)
    i += 1
    arg_types = []  # type: List[Type]
    arg_kinds = []  # type: List[int]
    while tokens[i].string != ')':
        if tokens[i].string == '*':
            arg_kinds.append(nodes.ARG_STAR)
            i += 1
        elif tokens[i].string == '**':
            arg_kinds.append(nodes.ARG_STAR2)
            i += 1
        else:
            arg_kinds.append(nodes.ARG_POS)
        arg, i = parse_type(tokens, i)
        arg_types.append(arg)
        next = tokens[i].string
        if next not in ',)':
            raise TypeParseError(tokens[i], i)
        if next == ',':
            i += 1
    i += 1
    if tokens[i].string != '->':
        raise TypeParseError(tokens[i], i)
    i += 1
    ret_type, i = parse_type(tokens, i)
    return CallableType(arg_types,
                    arg_kinds,
                    [None] * len(arg_types),
                    ret_type, None), i
Beispiel #49
0
def type_object_type(info: TypeInfo,
                     builtin_type: Callable[[str], Instance]) -> ProperType:
    """Return the type of a type object.

    For a generic type G with type variables T and S the type is generally of form

      Callable[..., G[T, S]]

    where ... are argument types for the __init__/__new__ method (without the self
    argument). Also, the fallback type will be 'type' instead of 'function'.
    """

    # We take the type from whichever of __init__ and __new__ is first
    # in the MRO, preferring __init__ if there is a tie.
    init_method = info.get('__init__')
    new_method = info.get('__new__')
    if not init_method or not is_valid_constructor(init_method.node):
        # Must be an invalid class definition.
        return AnyType(TypeOfAny.from_error)
    # There *should* always be a __new__ method except the test stubs
    # lack it, so just copy init_method in that situation
    new_method = new_method or init_method
    if not is_valid_constructor(new_method.node):
        # Must be an invalid class definition.
        return AnyType(TypeOfAny.from_error)

    # The two is_valid_constructor() checks ensure this.
    assert isinstance(new_method.node, (SYMBOL_FUNCBASE_TYPES, Decorator))
    assert isinstance(init_method.node, (SYMBOL_FUNCBASE_TYPES, Decorator))

    init_index = info.mro.index(init_method.node.info)
    new_index = info.mro.index(new_method.node.info)

    fallback = info.metaclass_type or builtin_type('builtins.type')
    if init_index < new_index:
        method = init_method.node  # type: Union[FuncBase, Decorator]
        is_new = False
    elif init_index > new_index:
        method = new_method.node
        is_new = True
    else:
        if init_method.node.info.fullname == 'builtins.object':
            # Both are defined by object.  But if we've got a bogus
            # base class, we can't know for sure, so check for that.
            if info.fallback_to_any:
                # Construct a universal callable as the prototype.
                any_type = AnyType(TypeOfAny.special_form)
                sig = CallableType(arg_types=[any_type, any_type],
                                   arg_kinds=[ARG_STAR, ARG_STAR2],
                                   arg_names=["_args", "_kwds"],
                                   ret_type=any_type,
                                   fallback=builtin_type('builtins.function'))
                return class_callable(sig, info, fallback, None, is_new=False)

        # Otherwise prefer __init__ in a tie. It isn't clear that this
        # is the right thing, but __new__ caused problems with
        # typeshed (#5647).
        method = init_method.node
        is_new = False
    # Construct callable type based on signature of __init__. Adjust
    # return type and insert type arguments.
    if isinstance(method, FuncBase):
        t = function_type(method, fallback)
    else:
        assert isinstance(method.type, ProperType)
        assert isinstance(method.type,
                          FunctionLike)  # is_valid_constructor() ensures this
        t = method.type
    return type_object_type_from_function(t, info, method.info, fallback,
                                          is_new)
Beispiel #50
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,
                                  override_column=n.col_offset,
                                  assume_str_is_unicode=self.unicode_literals)
        args, decompose_stmts = self.transform_args(n.args, lineno)
        if special_function_elide_names(n.name):
            for arg in args:
                arg.pos_only = True

        arg_kinds = [arg.kind for arg in args]
        arg_names = [
            None if arg.pos_only else arg.variable.name for arg in args
        ]

        arg_types: 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, n.col_offset)
            elif len(arg_types) > len(arg_kinds):
                self.fail('Type signature has too many arguments',
                          lineno,
                          n.col_offset,
                          blocker=False)
            elif len(arg_types) < len(arg_kinds):
                self.fail('Type signature has too few arguments',
                          lineno,
                          n.col_offset,
                          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: Statement = dec
        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
Beispiel #51
0
def is_callable_subtype(left: CallableType, right: CallableType,
                        ignore_return: bool = False,
                        ignore_pos_arg_names: bool = False) -> bool:
    """Is left a subtype of right?"""

    # If either function is implicitly typed, ignore positional arg names too
    if left.implicit or right.implicit:
        ignore_pos_arg_names = True

    # Non-type cannot be a subtype of type.
    if right.is_type_obj() and not left.is_type_obj():
        return False

    # A callable L is a subtype of a generic callable R if L is a
    # subtype of every type obtained from R by substituting types for
    # the variables of R. We can check this by simply leaving the
    # generic variables of R as type variables, effectively varying
    # over all possible values.

    # It's okay even if these variables share ids with generic
    # type variables of L, because generating and solving
    # constraints for the variables of L to make L a subtype of R
    # (below) treats type variables on the two sides as independent.

    if left.variables:
        # Apply generic type variables away in left via type inference.
        left = unify_generic_callable(left, right, ignore_return=ignore_return)
        if left is None:
            return False

    # Check return types.
    if not ignore_return and not is_subtype(left.ret_type, right.ret_type):
        return False

    if right.is_ellipsis_args:
        return True

    right_star_type = None   # type: Optional[Type]
    right_star2_type = None  # type: Optional[Type]

    # Match up corresponding arguments and check them for compatibility. In
    # every pair (argL, argR) of corresponding arguments from L and R, argL must
    # be "more general" than argR if L is to be a subtype of R.

    # Arguments are corresponding if they either share a name, share a position,
    # or both. If L's corresponding argument is ambiguous, L is not a subtype of
    # R.

    # If left has one corresponding argument by name and another by position,
    # consider them to be one "merged" argument (and not ambiguous) if they're
    # both optional, they're name-only and position-only respectively, and they
    # have the same type.  This rule allows functions with (*args, **kwargs) to
    # properly stand in for the full domain of formal arguments that they're
    # used for in practice.

    # Every argument in R must have a corresponding argument in L, and every
    # required argument in L must have a corresponding argument in R.
    done_with_positional = False
    for i in range(len(right.arg_types)):
        right_kind = right.arg_kinds[i]
        if right_kind in (ARG_STAR, ARG_STAR2, ARG_NAMED, ARG_NAMED_OPT):
            done_with_positional = True
        right_required = right_kind in (ARG_POS, ARG_NAMED)
        right_pos = None if done_with_positional else i

        right_arg = FormalArgument(
            right.arg_names[i],
            right_pos,
            right.arg_types[i],
            right_required)

        if right_kind == ARG_STAR:
            right_star_type = right_arg.typ
            # Right has an infinite series of optional positional arguments
            # here.  Get all further positional arguments of left, and make sure
            # they're more general than their corresponding member in this
            # series.  Also make sure left has its own inifite series of
            # optional positional arguments.
            if not left.is_var_arg:
                return False
            j = i
            while j < len(left.arg_kinds) and left.arg_kinds[j] in (ARG_POS, ARG_OPT):
                left_by_position = left.argument_by_position(j)
                assert left_by_position is not None
                # This fetches the synthetic argument that's from the *args
                right_by_position = right.argument_by_position(j)
                assert right_by_position is not None
                if not are_args_compatible(left_by_position, right_by_position,
                                           ignore_pos_arg_names):
                    return False
                j += 1
            continue

        if right_kind == ARG_STAR2:
            right_star2_type = right_arg.typ
            # Right has an infinite set of optional named arguments here.  Get
            # all further named arguments of left and make sure they're more
            # general than their corresponding member in this set.  Also make
            # sure left has its own infinite set of optional named arguments.
            if not left.is_kw_arg:
                return False
            left_names = {name for name in left.arg_names if name is not None}
            right_names = {name for name in right.arg_names if name is not None}
            left_only_names = left_names - right_names
            for name in left_only_names:
                left_by_name = left.argument_by_name(name)
                assert left_by_name is not None
                # This fetches the synthetic argument that's from the **kwargs
                right_by_name = right.argument_by_name(name)
                assert right_by_name is not None
                if not are_args_compatible(left_by_name, right_by_name,
                                           ignore_pos_arg_names):
                    return False
            continue

        # Left must have some kind of corresponding argument.
        left_arg = left.corresponding_argument(right_arg)
        if left_arg is None:
            return False

        if not are_args_compatible(left_arg, right_arg, ignore_pos_arg_names):
            return False

    done_with_positional = False
    for i in range(len(left.arg_types)):
        left_kind = left.arg_kinds[i]
        if left_kind in (ARG_STAR, ARG_STAR2, ARG_NAMED, ARG_NAMED_OPT):
            done_with_positional = True
        left_arg = FormalArgument(
            left.arg_names[i],
            None if done_with_positional else i,
            left.arg_types[i],
            left_kind in (ARG_POS, ARG_NAMED))

        # Check that *args and **kwargs types match in this loop
        if left_kind == ARG_STAR:
            if right_star_type is not None and not is_subtype(right_star_type, left_arg.typ):
                return False
            continue
        elif left_kind == ARG_STAR2:
            if right_star2_type is not None and not is_subtype(right_star2_type, left_arg.typ):
                return False
            continue

        right_by_name = (right.argument_by_name(left_arg.name)
                         if left_arg.name is not None
                         else None)

        right_by_pos = (right.argument_by_position(left_arg.pos)
                        if left_arg.pos is not None
                        else None)

        # If the left hand argument corresponds to two right-hand arguments,
        # neither of them can be required.
        if (right_by_name is not None
                and right_by_pos is not None
                and right_by_name != right_by_pos
                and (right_by_pos.required or right_by_name.required)):
            return False

        # All *required* left-hand arguments must have a corresponding
        # right-hand argument.  Optional args it does not matter.
        if left_arg.required and right_by_pos is None and right_by_name is None:
            return False

    return True
Beispiel #52
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
Beispiel #53
0
 def visit_callable_type(self, typ: CallableType) -> SnapshotItem:
     # FIX generics
     return ('CallableType', snapshot_types(typ.arg_types),
             snapshot_type(typ.ret_type), tuple(typ.arg_names),
             tuple(typ.arg_kinds), typ.is_type_obj(), typ.is_ellipsis_args)
Beispiel #54
0
    def visit_callable_type(self, template: CallableType) -> List[Constraint]:
        if isinstance(self.actual, CallableType):
            res: List[Constraint] = []
            cactual = self.actual
            param_spec = template.param_spec()
            if param_spec is None:
                # FIX verify argument counts
                # FIX what if one of the functions is generic

                # We can't infer constraints from arguments if the template is Callable[..., T]
                # (with literal '...').
                if not template.is_ellipsis_args:
                    # The lengths should match, but don't crash (it will error elsewhere).
                    for t, a in zip(template.arg_types, cactual.arg_types):
                        # Negate direction due to function argument type contravariance.
                        res.extend(
                            infer_constraints(t, a, neg_op(self.direction)))
            else:
                # TODO: Direction
                # TODO: Deal with arguments that come before param spec ones?
                res.append(
                    Constraint(param_spec.id, SUBTYPE_OF,
                               cactual.copy_modified(ret_type=NoneType())))

            template_ret_type, cactual_ret_type = template.ret_type, cactual.ret_type
            if template.type_guard is not None:
                template_ret_type = template.type_guard
            if cactual.type_guard is not None:
                cactual_ret_type = cactual.type_guard

            res.extend(
                infer_constraints(template_ret_type, cactual_ret_type,
                                  self.direction))
            return res
        elif isinstance(self.actual, AnyType):
            param_spec = template.param_spec()
            any_type = AnyType(TypeOfAny.from_another_any,
                               source_any=self.actual)
            if param_spec is None:
                # FIX what if generic
                res = self.infer_against_any(template.arg_types, self.actual)
            else:
                res = [
                    Constraint(
                        param_spec.id, SUBTYPE_OF,
                        callable_with_ellipsis(any_type, any_type,
                                               template.fallback))
                ]
            res.extend(
                infer_constraints(template.ret_type, any_type, self.direction))
            return res
        elif isinstance(self.actual, Overloaded):
            return self.infer_against_overloaded(self.actual, template)
        elif isinstance(self.actual, TypeType):
            return infer_constraints(template.ret_type, self.actual.item,
                                     self.direction)
        elif isinstance(self.actual, Instance):
            # Instances with __call__ method defined are considered structural
            # subtypes of Callable with a compatible signature.
            call = mypy.subtypes.find_member('__call__',
                                             self.actual,
                                             self.actual,
                                             is_operator=True)
            if call:
                return infer_constraints(template, call, self.direction)
            else:
                return []
        else:
            return []
Beispiel #55
0
def convert_class_tvars_to_func_tvars(callable: CallableType,
                                      num_func_tvars: int) -> CallableType:
    return cast(CallableType, callable.accept(TvarTranslator(num_func_tvars)))
Beispiel #56
0
 def callable(self, *a: Type) -> CallableType:
     """callable(a1, ..., an, r) constructs a callable with argument types
     a1, ... an and return type r.
     """
     return CallableType(list(a[:-1]), [ARG_POS] * (len(a) - 1),
                         [None] * (len(a) - 1), a[-1], self.function)
Beispiel #57
0
 def _add_bool_dunder(self, type_info: TypeInfo) -> None:
     signature = CallableType([], [], [], Instance(self.bool_type_info, []),
                              self.function)
     bool_func = FuncDef('__bool__', [], Block([]))
     bool_func.type = set_callable_name(signature, bool_func)
     type_info.names[bool_func.name] = SymbolTableNode(MDEF, bool_func)
Beispiel #58
0
 def visit_callable_type(self, t: CallableType) -> Type:
     return t.copy_modified(arg_types=self.expand_types(t.arg_types),
                            ret_type=t.ret_type.accept(self))
Beispiel #59
0
 def visit_callable_type(self, t: CallableType) -> Type:
     # We must preserve the fallback type for overload resolution to work.
     ret_type = NoneTyp()  # type: Type
     return CallableType([], [], [], ret_type, t.fallback)
Beispiel #60
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