コード例 #1
0
ファイル: subtypes.py プロジェクト: vnitinv/mypy
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
コード例 #2
0
 def visit_callable_type(self, t: CallableType) -> ProperType:
     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)
         # We set the from_type_type flag to suppress error when a collection of
         # concrete class objects gets inferred as their common abstract superclass.
         if not (
             (t.is_type_obj() and t.type_object().is_abstract) or
             (self.s.is_type_obj() and self.s.type_object().is_abstract)):
             result.from_type_type = True
         if isinstance(get_proper_type(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)
コード例 #3
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)
コード例 #4
0
ファイル: join.py プロジェクト: JamesTFarrington/mypy
 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)
コード例 #5
0
 def visit_callable_type(self, t: CallableType) -> ProperType:
     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 = join_similar_callables(t, self.s)
         # We set the from_type_type flag to suppress error when a collection of
         # concrete class objects gets inferred as their common abstract superclass.
         if not (
             (t.is_type_obj() and t.type_object().is_abstract) or
             (self.s.is_type_obj() and self.s.type_object().is_abstract)):
             result.from_type_type = True
         if any(
                 isinstance(tp, (NoneType, UninhabitedType))
                 for tp in get_proper_types(result.arg_types)):
             # We don't want to return unusable Callable, attempt fallback instead.
             return join_types(t.fallback, self.s)
         return result
     elif isinstance(self.s, Overloaded):
         # Switch the order of arguments to that we'll get to visit_overloaded.
         return join_types(t, self.s)
     elif isinstance(self.s, Instance) and self.s.type.is_protocol:
         call = unpack_callback_protocol(self.s)
         if call:
             return join_types(t, call)
     return join_types(t.fallback, self.s)
コード例 #6
0
ファイル: subtypes.py プロジェクト: gnprice/mypy
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
コード例 #7
0
ファイル: subtypes.py プロジェクト: bdarnell/mypy
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
コード例 #8
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)
コード例 #9
0
ファイル: astdiff.py プロジェクト: greatmazinger/mypy
 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)
コード例 #10
0
 def visit_callable_type(self, typ: CallableType) -> SnapshotItem:
     # FIX generics
     return ('CallableType',
             snapshot_types(typ.arg_types),
             snapshot_type(typ.ret_type),
             tuple([encode_optional_str(name) for name in typ.arg_names]),
             tuple(typ.arg_kinds),
             typ.is_type_obj(),
             typ.is_ellipsis_args)
コード例 #11
0
ファイル: astdiff.py プロジェクト: greatmazinger/mypy
 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
コード例 #12
0
ファイル: sametypes.py プロジェクト: JamesTFarrington/mypy
 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
コード例 #13
0
ファイル: astdiff.py プロジェクト: gknezevic/solution
 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
コード例 #14
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
コード例 #15
0
 def visit_callable_type(self, left: CallableType) -> bool:
     right = self.right
     if isinstance(right, CallableType):
         return is_callable_compatible(left, right, is_compat=is_proper_subtype)
     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
コード例 #16
0
ファイル: subtypes.py プロジェクト: vnitinv/mypy
 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
コード例 #17
0
ファイル: subtypes.py プロジェクト: noisecapella/mypy
 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
コード例 #18
0
ファイル: subtypes.py プロジェクト: edreamleo/mypy
 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
コード例 #19
0
ファイル: subtypes.py プロジェクト: greatmazinger/mypy
 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
コード例 #20
0
ファイル: subtypes.py プロジェクト: persianyagami/mypy
 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
コード例 #21
0
ファイル: meet.py プロジェクト: zadaya/CourseTB
 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)
コード例 #22
0
ファイル: meet.py プロジェクト: python/mypy
 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)
コード例 #23
0
def is_callable_compatible(left: CallableType, right: CallableType,
                           *,
                           is_compat: Callable[[Type, Type], bool],
                           is_compat_return: Optional[Callable[[Type, Type], bool]] = None,
                           ignore_return: bool = False,
                           ignore_pos_arg_names: bool = False,
                           check_args_covariantly: bool = False,
                           allow_partial_overlap: bool = False) -> bool:
    """Is the left compatible with the right, using the provided compatibility check?

    is_compat:
        The check we want to run against the parameters.

    is_compat_return:
        The check we want to run against the return type.
        If None, use the 'is_compat' check.

    check_args_covariantly:
        If true, check if the left's args is compatible with the right's
        instead of the other way around (contravariantly).

        This function is mostly used to check if the left is a subtype of the right which
        is why the default is to check the args contravariantly. However, it's occasionally
        useful to check the args using some other check, so we leave the variance
        configurable.

        For example, when checking the validity of overloads, it's useful to see if
        the first overload alternative has more precise arguments then the second.
        We would want to check the arguments covariantly in that case.

        Note! The following two function calls are NOT equivalent:

            is_callable_compatible(f, g, is_compat=is_subtype, check_args_covariantly=False)
            is_callable_compatible(g, f, is_compat=is_subtype, check_args_covariantly=True)

        The two calls are similar in that they both check the function arguments in
        the same direction: they both run `is_subtype(argument_from_g, argument_from_f)`.

        However, the two calls differ in which direction they check things like
        keyword arguments. For example, suppose f and g are defined like so:

            def f(x: int, *y: int) -> int: ...
            def g(x: int) -> int: ...

        In this case, the first call will succeed and the second will fail: f is a
        valid stand-in for g but not vice-versa.

    allow_partial_overlap:
        By default this function returns True if and only if *all* calls to left are
        also calls to right (with respect to the provided 'is_compat' function).

        If this parameter is set to 'True', we return True if *there exists at least one*
        call to left that's also a call to right.

        In other words, we perform an existential check instead of a universal one;
        we require left to only overlap with right instead of being a subset.

        For example, suppose we set 'is_compat' to some subtype check and compare following:

            f(x: float, y: str = "...", *args: bool) -> str
            g(*args: int) -> str

        This function would normally return 'False': f is not a subtype of g.
        However, we would return True if this parameter is set to 'True': the two
        calls are compatible if the user runs "f_or_g(3)". In the context of that
        specific call, the two functions effectively have signatures of:

            f2(float) -> str
            g2(int) -> str

        Here, f2 is a valid subtype of g2 so we return True.

        Specifically, if this parameter is set this function will:

        -   Ignore optional arguments on either the left or right that have no
            corresponding match.
        -   No longer mandate optional arguments on either side are also optional
            on the other.
        -   No longer mandate that if right has a *arg or **kwarg that left must also
            have the same.

        Note: when this argument is set to True, this function becomes "symmetric" --
        the following calls are equivalent:

            is_callable_compatible(f, g,
                                   is_compat=some_check,
                                   check_args_covariantly=False,
                                   allow_partial_overlap=True)
            is_callable_compatible(g, f,
                                   is_compat=some_check,
                                   check_args_covariantly=True,
                                   allow_partial_overlap=True)

        If the 'some_check' function is also symmetric, the two calls would be equivalent
        whether or not we check the args covariantly.
    """
    if is_compat_return is None:
        is_compat_return = is_compat

    # 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.
        unified = unify_generic_callable(left, right, ignore_return=ignore_return)
        if unified is None:
            return False
        else:
            left = unified

    # If we allow partial overlaps, we don't need to leave R generic:
    # if we can find even just a single typevar assignment which
    # would make these callables compatible, we should return True.

    # So, we repeat the above checks in the opposite direction. This also
    # lets us preserve the 'symmetry' property of allow_partial_overlap.
    if allow_partial_overlap and right.variables:
        unified = unify_generic_callable(right, left, ignore_return=ignore_return)
        if unified is not None:
            right = unified

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

    if check_args_covariantly:
        is_compat = flip_compat_check(is_compat)

    if right.is_ellipsis_args:
        return True

    left_star = left.var_arg
    left_star2 = left.kw_arg
    right_star = right.var_arg
    right_star2 = right.kw_arg

    # 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.

    # Phase 1: Confirm every argument in R has a corresponding argument in L.

    # Phase 1a: If left and right can both accept an infinite number of args,
    #           their types must be compatible.
    #
    #           Furthermore, if we're checking for compatibility in all cases,
    #           we confirm that if R accepts an infinite number of arguments,
    #           L must accept the same.
    def _incompatible(left_arg: Optional[FormalArgument],
                      right_arg: Optional[FormalArgument]) -> bool:
        if right_arg is None:
            return False
        if left_arg is None:
            return not allow_partial_overlap
        return not is_compat(right_arg.typ, left_arg.typ)

    if _incompatible(left_star, right_star) or _incompatible(left_star2, right_star2):
        return False

    # Phase 1b: Check non-star args: for every arg right can accept, left must
    #           also accept. The only exception is if we are allowing partial
    #           partial overlaps: in that case, we ignore optional args on the right.
    for right_arg in right.formal_arguments():
        left_arg = left.corresponding_argument(right_arg)
        if left_arg is None:
            if allow_partial_overlap and not right_arg.required:
                continue
            return False
        if not are_args_compatible(left_arg, right_arg, ignore_pos_arg_names,
                                   allow_partial_overlap, is_compat):
            return False

    # Phase 1c: Check var args. Right has an infinite series of optional positional
    #           arguments. Get all further positional args of left, and make sure
    #           they're more general then the corresponding member in right.
    if right_star is not None:
        # Synthesize an anonymous formal argument for the right
        right_by_position = right.try_synthesizing_arg_from_vararg(None)
        assert right_by_position is not None

        i = right_star.pos
        assert i is not None
        while i < len(left.arg_kinds) and left.arg_kinds[i] in (ARG_POS, ARG_OPT):
            if allow_partial_overlap and left.arg_kinds[i] == ARG_OPT:
                break

            left_by_position = left.argument_by_position(i)
            assert left_by_position is not None

            if not are_args_compatible(left_by_position, right_by_position,
                                       ignore_pos_arg_names, allow_partial_overlap,
                                       is_compat):
                return False
            i += 1

    # Phase 1d: Check kw args. Right has an infinite series of optional named
    #           arguments. Get all further named args of left, and make sure
    #           they're more general then the corresponding member in right.
    if right_star2 is not None:
        right_names = {name for name in right.arg_names if name is not None}
        left_only_names = set()
        for name, kind in zip(left.arg_names, left.arg_kinds):
            if name is None or kind in (ARG_STAR, ARG_STAR2) or name in right_names:
                continue
            left_only_names.add(name)

        # Synthesize an anonymous formal argument for the right
        right_by_name = right.try_synthesizing_arg_from_kwarg(None)
        assert right_by_name is not None

        for name in left_only_names:
            left_by_name = left.argument_by_name(name)
            assert left_by_name is not None

            if allow_partial_overlap and not left_by_name.required:
                continue

            if not are_args_compatible(left_by_name, right_by_name, ignore_pos_arg_names,
                                       allow_partial_overlap, is_compat):
                return False

    # Phase 2: Left must not impose additional restrictions.
    #          (Every required argument in L must have a corresponding argument in R)
    #          Note: we already checked the *arg and **kwarg arguments in phase 1a.
    for left_arg in left.formal_arguments():
        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 do not matter.
        if left_arg.required and right_by_pos is None and right_by_name is None:
            return False

    return True
コード例 #24
0
ファイル: subtypes.py プロジェクト: persianyagami/mypy
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
コード例 #25
0
ファイル: subtypes.py プロジェクト: troyboy1102/Python
def is_callable_compatible(left: CallableType,
                           right: CallableType,
                           *,
                           is_compat: Callable[[Type, Type], bool],
                           is_compat_return: Optional[Callable[[Type, Type],
                                                               bool]] = None,
                           ignore_return: bool = False,
                           ignore_pos_arg_names: bool = False,
                           check_args_covariantly: bool = False) -> bool:
    """Is the left compatible with the right, using the provided compatibility check?

    is_compat:
        The check we want to run against the parameters.

    is_compat_return:
        The check we want to run against the return type.
        If None, use the 'is_compat' check.

    check_args_covariantly:
        If true, check if the left's args is compatible with the right's
        instead of the other way around (contravariantly).

        This function is mostly used to check if the left is a subtype of the right which
        is why the default is to check the args contravariantly. However, it's occasionally
        useful to check the args using some other check, so we leave the variance
        configurable.

        For example, when checking the validity of overloads, it's useful to see if
        the first overload alternative has more precise arguments then the second.
        We would want to check the arguments covariantly in that case.

        Note! The following two function calls are NOT equivalent:

            is_callable_compatible(f, g, is_compat=is_subtype, check_args_covariantly=False)
            is_callable_compatible(g, f, is_compat=is_subtype, check_args_covariantly=True)

        The two calls are similar in that they both check the function arguments in
        the same direction: they both run `is_subtype(argument_from_g, argument_from_f)`.

        However, the two calls differ in which direction they check things likee
        keyword arguments. For example, suppose f and g are defined like so:

            def f(x: int, *y: int) -> int: ...
            def g(x: int) -> int: ...

        In this case, the first call will succeed and the second will fail: f is a
        valid stand-in for g but not vice-versa.
    """
    if is_compat_return is None:
        is_compat_return = is_compat

    # 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.
        unified = unify_generic_callable(left,
                                         right,
                                         ignore_return=ignore_return)
        if unified is None:
            return False
        else:
            left = unified

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

    if check_args_covariantly:
        is_compat = flip_compat_check(is_compat)

    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 infinite 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, is_compat):
                    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, is_compat):
                    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,
                                   is_compat):
            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_compat(
                    right_star_type, left_arg.typ):
                return False
            continue
        elif left_kind == ARG_STAR2:
            if right_star2_type is not None and not is_compat(
                    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