Beispiel #1
0
def is_proper_subtype(t: Type, s: Type) -> bool:
    """Check if t is a proper subtype of s?

    For proper subtypes, there's no need to rely on compatibility due to
    Any types. Any instance type t is also a proper subtype of t.
    """
    # FIX tuple types
    if isinstance(t, Instance):
        if isinstance(s, Instance):
            if not t.type.has_base(s.type.fullname()):
                return False

            def check_argument(left: Type, right: Type, variance: int) -> bool:
                if variance == COVARIANT:
                    return is_proper_subtype(left, right)
                elif variance == CONTRAVARIANT:
                    return is_proper_subtype(right, left)
                else:
                    return sametypes.is_same_type(left, right)

            # Map left type to corresponding right instances.
            t = map_instance_to_supertype(t, s.type)

            return all(check_argument(ta, ra, tvar.variance) for ta, ra, tvar in
                       zip(t.args, s.args, s.type.defn.type_vars))
        return False
    else:
        return sametypes.is_same_type(t, s)
Beispiel #2
0
 def visit_intersection(self, t):
     # TODO Obsolete; target overload types instead?
     # Only support very rudimentary meets between intersection types.
     if is_same_type(self.s, t):
         return self.s
     else:
         return self.default(self.s)
Beispiel #3
0
 def check_argument(left: Type, right: Type, variance: int) -> bool:
     if variance == COVARIANT:
         return is_proper_subtype(left, right)
     elif variance == CONTRAVARIANT:
         return is_proper_subtype(right, left)
     else:
         return sametypes.is_same_type(left, right)
Beispiel #4
0
 def check_type_var_values(self, type: TypeInfo, actuals: List[Type],
                           valids: List[Type], context: Context) -> None:
     for actual in actuals:
         if (not isinstance(actual, AnyType) and
                 not any(is_same_type(actual, value) for value in valids)):
             self.fail('Invalid type argument value for "{}"'.format(
                 type.name()), context)
Beispiel #5
0
 def add_symbol(self, name: str, node: SymbolTableNode,
                context: Context) -> None:
     # NOTE: This is closely related to SemanticAnalyzerPass2.add_symbol. Since both methods
     #     will be called on top-level definitions, they need to co-operate. If you change
     #     this, you may have to change the other method as well.
     if self.sem.is_func_scope():
         assert self.sem.locals[-1] is not None
         if name in self.sem.locals[-1]:
             # Flag redefinition unless this is a reimport of a module.
             if not (node.kind == MODULE_REF and
                     self.sem.locals[-1][name].node == node.node):
                 self.sem.name_already_defined(name, context)
         self.sem.locals[-1][name] = node
     else:
         assert self.sem.type is None  # Pass 1 doesn't look inside classes
         existing = self.sem.globals.get(name)
         if (existing
                 and (not isinstance(node.node, MypyFile) or existing.node != node.node)
                 and existing.kind != UNBOUND_IMPORTED
                 and not isinstance(existing.node, ImportedName)):
             # Modules can be imported multiple times to support import
             # of multiple submodules of a package (e.g. a.x and a.y).
             ok = False
             # Only report an error if the symbol collision provides a different type.
             if existing.type and node.type and is_same_type(existing.type, node.type):
                 ok = True
             if not ok:
                 self.sem.name_already_defined(name, context)
         elif not existing:
             self.sem.globals[name] = node
Beispiel #6
0
def is_proper_subtype(t: Type, s: Type) -> bool:
    """Check if t is a proper subtype of s?

    For proper subtypes, there's no need to rely on compatibility due to
    Any types. Any instance type t is also a proper subtype of t.
    """
    # FIX tuple types
    if isinstance(t, Instance):
        if isinstance(s, Instance):
            if not t.type.has_base(s.type.fullname()):
                return False
            t = map_instance_to_supertype(t, s.type)
            return all(sametypes.is_same_type(x, y)
                       for x, y in zip(t.args, s.args))
        return False
    else:
        return sametypes.is_same_type(t, s)
Beispiel #7
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 #8
0
    def update_from_options(self, frames: List[Frame]) -> bool:
        """Update the frame to reflect that each key will be updated
        as in one of the frames.  Return whether any item changes.

        If a key is declared as AnyType, only update it if all the
        options are the same.
        """

        frames = [f for f in frames if not f.unreachable]
        changed = False
        keys = set(key for f in frames for key in f)

        for key in keys:
            current_value = self._get(key)
            resulting_values = [f.get(key, current_value) for f in frames]
            if any(x is None for x in resulting_values):
                # We didn't know anything about key before
                # (current_value must be None), and we still don't
                # know anything about key in at least one possible frame.
                continue

            type = resulting_values[0]
            assert type is not None
            declaration_type = self.declarations.get(key)
            if isinstance(declaration_type, AnyType):
                # At this point resulting values can't contain None, see continue above
                if not all(
                        is_same_type(type, cast(Type, t))
                        for t in resulting_values[1:]):
                    type = AnyType(TypeOfAny.from_another_any,
                                   source_any=declaration_type)
            else:
                for other in resulting_values[1:]:
                    assert other is not None
                    type = join_simple(self.declarations[key], type, other)
            if current_value is None or not is_same_type(type, current_value):
                self._put(key, type)
                changed = True

        self.frames[-1].unreachable = not frames

        return changed
Beispiel #9
0
    def assert_simple_is_same(self, s: Type, t: Type, expected: bool, strict: bool) -> None:
        actual = is_same_type(s, t)
        assert_equal(actual, expected,
                     'is_same_type({}, {}) is {{}} ({{}} expected)'.format(s, t))

        if strict:
            actual2 = (s == t)
            assert_equal(actual2, expected,
                         '({} == {}) is {{}} ({{}} expected)'.format(s, t))
            assert_equal(hash(s) == hash(t), expected,
                         '(hash({}) == hash({}) is {{}} ({{}} expected)'.format(s, t))
Beispiel #10
0
 def visit_typeddict_type(self, left: TypedDictType) -> bool:
     right = self.right
     if isinstance(right, TypedDictType):
         for name, typ in left.items.items():
             if name in right.items and not is_same_type(typ, right.items[name]):
                 return False
         for name, typ in right.items.items():
             if name not in left.items:
                 return False
         return True
     return is_proper_subtype(left.fallback, right)
Beispiel #11
0
 def visit_typeddict_type(self, left: TypedDictType) -> bool:
     right = self.right
     if isinstance(right, TypedDictType):
         for name, typ in left.items.items():
             if name in right.items and not is_same_type(typ, right.items[name]):
                 return False
         for name, typ in right.items.items():
             if name not in left.items:
                 return False
         return True
     return is_proper_subtype(left.fallback, right)
Beispiel #12
0
 def check_type_var_values(self, type: TypeInfo, actuals: List[Type],
                           valids: List[Type], arg_number: int, context: Context) -> None:
     for actual in actuals:
         if (not isinstance(actual, AnyType) and
                 not any(is_same_type(actual, value) for value in valids)):
             if len(actuals) > 1 or not isinstance(actual, Instance):
                 self.fail('Invalid type argument value for "{}"'.format(
                     type.name()), context)
             else:
                 self.fail('Type argument {} of "{}" has incompatible value "{}"'.format(
                     arg_number, type.name(), actual.type.name()), context)
Beispiel #13
0
    def test_literal_type(self) -> None:
        a = self.fx.a
        lit1 = self.fx.lit1
        lit2 = self.fx.lit2
        lit3 = self.fx.lit3

        self.assert_meet(lit1, lit1, lit1)
        self.assert_meet(lit1, a, lit1)
        self.assert_meet_uninhabited(lit1, lit3)
        self.assert_meet_uninhabited(lit1, lit2)
        self.assert_meet(UnionType([lit1, lit2]), lit1, lit1)
        self.assert_meet(UnionType([lit1, lit2]), UnionType([lit2, lit3]),
                         lit2)
        self.assert_meet(UnionType([lit1, lit2]), UnionType([lit1, lit2]),
                         UnionType([lit1, lit2]))
        self.assert_meet(lit1, self.fx.anyt, lit1)
        self.assert_meet(lit1, self.fx.o, lit1)

        assert is_same_type(lit1, narrow_declared_type(lit1, a))
        assert is_same_type(lit2, narrow_declared_type(lit2, a))
Beispiel #14
0
 def check_type_var_values(self, type: TypeInfo, actuals: List[Type],
                           valids: List[Type], arg_number: int, context: Context) -> None:
     for actual in actuals:
         if (not isinstance(actual, AnyType) and
                 not any(is_same_type(actual, value) for value in valids)):
             if len(actuals) > 1 or not isinstance(actual, Instance):
                 self.fail('Invalid type argument value for "{}"'.format(
                     type.name()), context)
             else:
                 self.fail('Type argument {} of "{}" has incompatible value "{}"'.format(
                     arg_number, type.name(), actual.type.name()), context)
Beispiel #15
0
    def assert_simple_is_same(self, s: Type, t: Type, expected: bool, strict: bool) -> None:
        actual = is_same_type(s, t)
        assert_equal(actual, expected,
                     'is_same_type({}, {}) is {{}} ({{}} expected)'.format(s, t))

        if strict:
            actual2 = (s == t)
            assert_equal(actual2, expected,
                         '({} == {}) is {{}} ({{}} expected)'.format(s, t))
            assert_equal(hash(s) == hash(t), expected,
                         '(hash({}) == hash({}) is {{}} ({{}} expected)'.format(s, t))
Beispiel #16
0
def generate_type_combinations(types: List[Type]) -> List[Type]:
    """Generate possible combinations of a list of types.

    mypy essentially supports two different ways to do this: joining the types
    and unioning the types. We try both.
    """
    joined_type = join_type_list(types)
    union_type = make_simplified_union(types)
    if is_same_type(joined_type, union_type):
        return [joined_type]
    else:
        return [joined_type, union_type]
Beispiel #17
0
def is_proper_subtype(t: Type, s: Type) -> bool:
    """Check if t is a proper subtype of s?

    For proper subtypes, there's no need to rely on compatibility due to
    Any types. Any instance type t is also a proper subtype of t.
    """
    # FIX tuple types
    if isinstance(t, Instance):
        if isinstance(s, Instance):
            if not t.type.has_base(s.type.fullname()):
                return False
            t = map_instance_to_supertype(t, s.type)
            if not is_immutable(s):
                return all(sametypes.is_same_type(ta, ra) for (ta, ra) in
                           zip(t.args, s.args))
            else:
                return all(is_proper_subtype(ta, ra) for (ta, ra) in
                           zip(t.args, s.args))
        return False
    else:
        return sametypes.is_same_type(t, s)
Beispiel #18
0
def zerodim_to_scalar(typ: Type) -> Type:
    if is_subtype(
            typ,
            API.named_generic_type(
                'numpy.ndarray',
                args=[
                    AnyType(TypeOfAny.unannotated),
                    API.named_type('numpy.ZeroD')
                ])) and (not is_same_type(typ.args[1],
                                          AnyType(TypeOfAny.unannotated))):
        return typ.args[0]
    return typ
Beispiel #19
0
    def test_literal_type(self) -> None:
        a = self.fx.a
        d = self.fx.d
        lit1 = LiteralType(1, a)
        lit2 = LiteralType(2, a)
        lit3 = LiteralType("foo", d)

        self.assert_meet(lit1, lit1, lit1)
        self.assert_meet(lit1, a, lit1)
        self.assert_meet_uninhabited(lit1, lit3)
        self.assert_meet_uninhabited(lit1, lit2)
        self.assert_meet(UnionType([lit1, lit2]), lit1, lit1)
        self.assert_meet(UnionType([lit1, lit2]), UnionType([lit2, lit3]),
                         lit2)
        self.assert_meet(UnionType([lit1, lit2]), UnionType([lit1, lit2]),
                         UnionType([lit1, lit2]))
        self.assert_meet(lit1, self.fx.anyt, lit1)
        self.assert_meet(lit1, self.fx.o, lit1)

        assert_true(is_same_type(lit1, narrow_declared_type(lit1, a)))
        assert_true(is_same_type(lit2, narrow_declared_type(lit2, a)))
Beispiel #20
0
def generate_type_combinations(types: List[Type]) -> List[Type]:
    """Generate possible combinations of a list of types.

    mypy essentially supports two different ways to do this: joining the types
    and unioning the types. We try both.
    """
    joined_type = join_type_list(types)
    union_type = UnionType.make_simplified_union(types)
    if is_same_type(joined_type, union_type):
        return [joined_type]
    else:
        return [joined_type, union_type]
Beispiel #21
0
def is_more_precise(t: Type, s: Type) -> bool:
    """Check if t is a more precise type than s.

    A t is a proper subtype of s, t is also more precise than s. Also, if
    s is Any, t is more precise than s for any t. Finally, if t is the same
    type as s, t is more precise than s.
    """
    # TODO Should List[int] be more precise than List[Any]?
    if isinstance(s, AnyType):
        return True
    if isinstance(s, Instance):
        return is_proper_subtype(t, s)
    return sametypes.is_same_type(t, s)
Beispiel #22
0
def is_ndarray_of_ints(typ: Type, no_bools: bool = True):
    if not isinstance(typ, Instance):
        return False
    of_ints = is_subtype(
        typ,
        API.named_generic_type(
            'numpy.ndarray',
            args=[int_type(), API.named_type('numpy._Dimension')])) and (
                not is_same_type(typ.args[1], AnyType(TypeOfAny.unannotated)))

    if not no_bools:
        return of_ints
    return of_ints and not is_ndarray_of_bools(typ)
Beispiel #23
0
    def update_from_options(self, frames: List[Frame]) -> bool:
        """Update the frame to reflect that each key will be updated
        as in one of the frames.  Return whether any item changes.

        If a key is declared as AnyType, only update it if all the
        options are the same.
        """

        frames = [f for f in frames if not f.unreachable]
        changed = False
        keys = set(key for f in frames for key in f)

        for key in keys:
            current_value = self._get(key)
            resulting_values = [f.get(key, current_value) for f in frames]
            if any(x is None for x in resulting_values):
                # We didn't know anything about key before
                # (current_value must be None), and we still don't
                # know anything about key in at least one possible frame.
                continue

            type = resulting_values[0]
            assert type is not None
            declaration_type = self.declarations.get(key)
            if isinstance(declaration_type, AnyType):
                # At this point resulting values can't contain None, see continue above
                if not all(is_same_type(type, cast(Type, t)) for t in resulting_values[1:]):
                    type = AnyType(TypeOfAny.from_another_any, source_any=declaration_type)
            else:
                for other in resulting_values[1:]:
                    assert other is not None
                    type = join_simple(self.declarations[key], type, other)
            if current_value is None or not is_same_type(type, current_value):
                self._put(key, type)
                changed = True

        self.frames[-1].unreachable = not frames

        return changed
Beispiel #24
0
def is_more_precise(t: Type, s: Type) -> bool:
    """Check if t is a more precise type than s.

    A t is a proper subtype of s, t is also more precise than s. Also, if
    s is Any, t is more precise than s for any t. Finally, if t is the same
    type as s, t is more precise than s.
    """
    # TODO Should List[int] be more precise than List[Any]?
    if isinstance(s, AnyType):
        return True
    if isinstance(s, Instance):
        return is_proper_subtype(t, s)
    return sametypes.is_same_type(t, s)
Beispiel #25
0
 def check_type_var_values(self, type: TypeInfo, actuals: List[Type], arg_name: str,
                           valids: List[Type], arg_number: int, context: Context) -> None:
     for actual in actuals:
         if (not isinstance(actual, AnyType) and
                 not any(is_same_type(actual, value)
                         for value in valids)):
             if len(actuals) > 1 or not isinstance(actual, Instance):
                 self.fail('Invalid type argument value for "{}"'.format(
                     type.name()), context)
             else:
                 class_name = '"{}"'.format(type.name())
                 actual_type_name = '"{}"'.format(actual.type.name())
                 self.fail(messages.INCOMPATIBLE_TYPEVAR_VALUE.format(
                     arg_name, class_name, actual_type_name), context)
Beispiel #26
0
 def check_type_var_values(self, type: TypeInfo, actuals: List[Type], arg_name: str,
                           valids: List[Type], arg_number: int, context: Context) -> None:
     for actual in actuals:
         if (not isinstance(actual, AnyType) and
                 not any(is_same_type(actual, value)
                         for value in valids)):
             if len(actuals) > 1 or not isinstance(actual, Instance):
                 self.fail('Invalid type argument value for "{}"'.format(
                     type.name()), context)
             else:
                 class_name = '"{}"'.format(type.name())
                 actual_type_name = '"{}"'.format(actual.type.name())
                 self.fail(messages.INCOMPATIBLE_TYPEVAR_VALUE.format(
                     arg_name, class_name, actual_type_name), context)
Beispiel #27
0
def check_instance_definition(
    passed_types: TupleType,
    instance_signature: CallableType,
    fullname: str,
    ctx: MethodContext,
) -> _RuntimeValidationContext:
    """
    Checks runtime type.

    We call "runtime types" things that we use at runtime to dispatch our calls.
    For example:

    1. We check that type passed in ``some.instance(...)`` matches
       one defined in a type annotation
    2. We check that types don't have any concrete types
    3. We check that types don't have any unbound type variables
    4. We check that ``is_protocol`` is passed correctly

    """
    runtime_type = inference.infer_runtime_type_from_context(
        fallback=passed_types.items[0],
        fullname=fullname,
        ctx=ctx,
    )

    if len(passed_types.items) == 2:
        is_protocol, protocol_arg_check = _check_protocol_arg(passed_types, ctx)
    else:
        is_protocol = False
        protocol_arg_check = True

    instance_type = instance_signature.arg_types[0]
    instance_check = is_same_type(
        erase_type(instance_type),
        erase_type(runtime_type),
    )
    if not instance_check:
        ctx.api.fail(
            _INSTANCE_RUNTIME_MISMATCH_MSG.format(instance_type, runtime_type),
            ctx.context,
        )

    return _RuntimeValidationContext(runtime_type, is_protocol, all([
        _check_runtime_protocol(runtime_type, ctx, is_protocol=is_protocol),
        _check_concrete_generics(runtime_type, instance_type, ctx),
        _check_tuple_size(instance_type, ctx),
        protocol_arg_check,
        instance_check,
    ]))
Beispiel #28
0
def is_more_precise(t: Type, s: Type) -> bool:
    """Check if t is a more precise type than s.

    A t is a proper subtype of s, t is also more precise than s. Also, if
    s is Any, t is more precise than s for any t. Finally, if t is the same
    type as s, t is more precise than s.
    """
    # TODO Should List[int] be more precise than List[Any]?
    if isinstance(s, AnyType):
        return True
    if isinstance(s, Instance):
        if isinstance(t, CallableType):
            # Fall back to subclass check and ignore other properties of the callable.
            return is_proper_subtype(t.fallback, s)
        return is_proper_subtype(t, s)
    return sametypes.is_same_type(t, s)
Beispiel #29
0
    def is_valid_inferred_type(self, typ):
        """Is an inferred type invalid?

        Examples include the None type or a type with a None component.
        """
        if is_same_type(typ, NoneTyp()):
            return False
        elif isinstance(typ, Instance):
            for arg in (typ).args:
                if not self.is_valid_inferred_type(arg):
                    return False
        elif isinstance(typ, TupleType):
            for item in (typ).items:
                if not self.is_valid_inferred_type(item):
                    return False
        return True
Beispiel #30
0
def is_trivial_coercion(target_type, source_type, is_java):
    """Is an implicit coercion from source_type to target_type a no-op?

    Note that we omit coercions of form any <= C, unless C is a primitive that
    may have a special representation.
    """
    # FIX: Replace type vars in source type with any?
    if isinstance(source_type, Void) or is_same_type(target_type, source_type):
        return True
    
    # Coercions from a primitive type to any other type are non-trivial, since
    # we may have to change the representation.
    if not is_java and is_special_primitive(source_type):
        return False
    
    return (is_proper_subtype(source_type, target_type)
            or isinstance(source_type, NoneTyp)
            or isinstance(target_type, Any))
Beispiel #31
0
def is_trivial_coercion(target_type: Type, source_type: Type,
                        is_java: bool) -> bool:
    """Is an implicit coercion from source_type to target_type a no-op?

    Note that we omit coercions of form any <= C, unless C is a primitive that
    may have a special representation.
    """
    # FIX: Replace type vars in source type with any?
    if isinstance(source_type, Void) or is_same_type(target_type, source_type):
        return True

    # Coercions from a primitive type to any other type are non-trivial, since
    # we may have to change the representation.
    if not is_java and is_special_primitive(source_type):
        return False

    return (is_proper_subtype(source_type, target_type)
            or isinstance(source_type, NoneTyp)
            or isinstance(target_type, AnyType))
Beispiel #32
0
def is_simple_override(fdef, info):
    """Is function an override with the same type precision as the original?
    
    Compare to the original method in the superclass of info.
    """
    # If this is not an override, this can't be a simple override either.
    # Generic inheritance is not currently supported, since we need to map
    # type variables between types; in the future this restriction can be
    # lifted.
    if info.base is None or info.base.type_vars != []:
        return False
    orig = info.base.get_method(fdef.name())
    # Ignore the first argument (self) when determining type sameness.
    # TODO overloads
    newtype = function_type(fdef)
    newtype = replace_self_type(newtype, Any())
    origtype = function_type(orig)
    origtype = replace_self_type(origtype, Any())
    return is_same_type(newtype, origtype)
Beispiel #33
0
 def check_type_var_values(self, type: TypeInfo, actuals: List[Type],
                           arg_name: str, valids: List[Type],
                           arg_number: int, context: Context) -> None:
     for actual in get_proper_types(actuals):
         if (not isinstance(actual, AnyType) and
                 not any(is_same_type(actual, value) for value in valids)):
             if len(actuals) > 1 or not isinstance(actual, Instance):
                 self.fail(
                     message_registry.INVALID_TYPEVAR_ARG_VALUE.format(
                         type.name),
                     context,
                     code=codes.TYPE_VAR)
             else:
                 class_name = '"{}"'.format(type.name)
                 actual_type_name = '"{}"'.format(actual.type.name)
                 self.fail(
                     message_registry.INCOMPATIBLE_TYPEVAR_VALUE.format(
                         arg_name, class_name, actual_type_name),
                     context,
                     code=codes.TYPE_VAR)
Beispiel #34
0
def is_simple_override(fdef: FuncDef, info: TypeInfo) -> bool:
    """Is function an override with the same type precision as the original?

    Compare to the original method in the superclass of info.
    """
    # If this is not an override, this can't be a simple override either.
    # Generic inheritance is not currently supported, since we need to map
    # type variables between types; in the future this restriction can be
    # lifted.
    if len(info.mro) <= 1:
        return False
    base = info.mro[1]
    if base.type_vars != []:
        return False
    orig = base.get_method(fdef.name())
    # Ignore the first argument (self) when determining type sameness.
    # TODO overloads
    newtype = cast(Callable, function_type(fdef))
    newtype = replace_leading_arg_type(newtype, AnyType())
    origtype = cast(Callable, function_type(orig))
    origtype = replace_leading_arg_type(origtype, AnyType())
    return is_same_type(newtype, origtype)
Beispiel #35
0
def is_simple_override(fdef: FuncDef, info: TypeInfo) -> bool:
    """Is function an override with the same type precision as the original?
    
    Compare to the original method in the superclass of info.
    """
    # If this is not an override, this can't be a simple override either.
    # Generic inheritance is not currently supported, since we need to map
    # type variables between types; in the future this restriction can be
    # lifted.
    if len(info.mro) <= 1:
        return False
    base = info.mro[1]
    if base.type_vars != []:
        return False
    orig = base.get_method(fdef.name())
    # Ignore the first argument (self) when determining type sameness.
    # TODO overloads
    newtype = cast(Callable, function_type(fdef))
    newtype = replace_self_type(newtype, AnyType())
    origtype = cast(Callable, function_type(orig))
    origtype = replace_self_type(origtype, AnyType())
    return is_same_type(newtype, origtype)
Beispiel #36
0
def is_ellipsis(type: Type):
    return is_same_type(type, API.named_type('builtins.ellipsis'))
Beispiel #37
0
def is_list_of_int(type: Type):
    return is_same_type(
        type, API.named_generic_type('builtins.list', args=[int_type()]))
Beispiel #38
0
def is_slice(type: Type):
    return is_same_type(type, API.named_type('builtins.slice'))
Beispiel #39
0
 def visit_instance(self, template: Instance) -> List[Constraint]:
     original_actual = actual = self.actual
     res = []  # type: List[Constraint]
     if isinstance(
             actual,
         (CallableType, Overloaded)) and template.type.is_protocol:
         if template.type.protocol_members == ['__call__']:
             # Special case: a generic callback protocol
             if not any(
                     is_same_type(template, t)
                     for t in template.type.inferring):
                 template.type.inferring.append(template)
                 call = mypy.subtypes.find_member('__call__', template,
                                                  actual)
                 assert call is not None
                 if mypy.subtypes.is_subtype(actual, erase_typevars(call)):
                     subres = infer_constraints(call, actual,
                                                self.direction)
                     res.extend(subres)
                 template.type.inferring.pop()
                 return res
     if isinstance(actual, CallableType) and actual.fallback is not None:
         actual = actual.fallback
     if isinstance(actual, Overloaded) and actual.fallback is not None:
         actual = actual.fallback
     if isinstance(actual, TypedDictType):
         actual = actual.as_anonymous().fallback
     if isinstance(actual, Instance):
         instance = actual
         erased = erase_typevars(template)
         assert isinstance(erased, Instance)
         # We always try nominal inference if possible,
         # it is much faster than the structural one.
         if (self.direction == SUBTYPE_OF
                 and template.type.has_base(instance.type.fullname())):
             mapped = map_instance_to_supertype(template, instance.type)
             for i in range(len(instance.args)):
                 # The constraints for generic type parameters are
                 # invariant. Include constraints from both directions
                 # to achieve the effect.
                 res.extend(
                     infer_constraints(mapped.args[i], instance.args[i],
                                       self.direction))
                 res.extend(
                     infer_constraints(mapped.args[i], instance.args[i],
                                       neg_op(self.direction)))
             return res
         elif (self.direction == SUPERTYPE_OF
               and instance.type.has_base(template.type.fullname())):
             mapped = map_instance_to_supertype(instance, template.type)
             for j in range(len(template.args)):
                 # The constraints for generic type parameters are
                 # invariant.
                 res.extend(
                     infer_constraints(template.args[j], mapped.args[j],
                                       self.direction))
                 res.extend(
                     infer_constraints(template.args[j], mapped.args[j],
                                       neg_op(self.direction)))
             return res
         if (template.type.is_protocol and self.direction == SUPERTYPE_OF
                 and
                 # We avoid infinite recursion for structural subtypes by checking
                 # whether this type already appeared in the inference chain.
                 # This is a conservative way break the inference cycles.
                 # It never produces any "false" constraints but gives up soon
                 # on purely structural inference cycles, see #3829.
                 # Note that we use is_protocol_implementation instead of is_subtype
                 # because some type may be considered a subtype of a protocol
                 # due to _promote, but still not implement the protocol.
                 not any(
                     is_same_type(template, t)
                     for t in template.type.inferring)
                 and mypy.subtypes.is_protocol_implementation(
                     instance, erased)):
             template.type.inferring.append(template)
             self.infer_constraints_from_protocol_members(
                 res, instance, template, original_actual, template)
             template.type.inferring.pop()
             return res
         elif (instance.type.is_protocol and self.direction == SUBTYPE_OF
               and
               # We avoid infinite recursion for structural subtypes also here.
               not any(
                   is_same_type(instance, i)
                   for i in instance.type.inferring)
               and mypy.subtypes.is_protocol_implementation(
                   erased, instance)):
             instance.type.inferring.append(instance)
             self.infer_constraints_from_protocol_members(
                 res, instance, template, template, instance)
             instance.type.inferring.pop()
             return res
     if isinstance(actual, AnyType):
         # IDEA: Include both ways, i.e. add negation as well?
         return self.infer_against_any(template.args, actual)
     if (isinstance(actual, TupleType)
             and (is_named_instance(template, 'typing.Iterable')
                  or is_named_instance(template, 'typing.Container')
                  or is_named_instance(template, 'typing.Sequence')
                  or is_named_instance(template, 'typing.Reversible'))
             and self.direction == SUPERTYPE_OF):
         for item in actual.items:
             cb = infer_constraints(template.args[0], item, SUPERTYPE_OF)
             res.extend(cb)
         return res
     elif isinstance(actual, TupleType) and self.direction == SUPERTYPE_OF:
         return infer_constraints(template, actual.fallback, self.direction)
     else:
         return []
Beispiel #40
0
 def visit_intersection(self, t):
     # Only support very rudimentary meets between intersection types.
     if is_same_type(self.s, t):
         return self.s
     else:
         return self.default(self.s)
Beispiel #41
0
    Compare to the original method in the superclass of info.
    """
    # If this is not an override, this can't be a simple override either.
    # Generic inheritance is not currently supported, since we need to map
    # type variables between types; in the future this restriction can be
    # lifted.
    if info.base is None or info.base.type_vars != []:
        return False
    orig = info.base.get_method(fdef.name())
    # Ignore the first argument (self) when determining type sameness.
    # TODO overloads
    newtype = (Callable)function_type(fdef)
    newtype = replace_self_type(newtype, Any())
    origtype = (Callable)function_type(orig)
    origtype = replace_self_type(origtype, Any())
    return is_same_type(newtype, origtype)


str tvar_slot_name(int n, any is_alt=False):
    """Return the name of the member that holds the runtime value of the given
    type variable slot.
    """
    if is_alt != BOUND_VAR:
        if n == 0:
            return '__tv'
        else:
            return '__tv{}'.format(n + 1)
    else:
        # Greatest lower bound
        if n == 0:
            return '__btv'
Beispiel #42
0
 def visit_instance(self, template: Instance) -> List[Constraint]:
     original_actual = actual = self.actual
     res = []  # type: List[Constraint]
     if isinstance(actual, CallableType) and actual.fallback is not None:
         actual = actual.fallback
     if isinstance(actual, TypedDictType):
         actual = actual.as_anonymous().fallback
     if isinstance(actual, Instance):
         instance = actual
         # We always try nominal inference if possible,
         # it is much faster than the structural one.
         if (self.direction == SUBTYPE_OF and
                 template.type.has_base(instance.type.fullname())):
             mapped = map_instance_to_supertype(template, instance.type)
             for i in range(len(instance.args)):
                 # The constraints for generic type parameters are
                 # invariant. Include constraints from both directions
                 # to achieve the effect.
                 res.extend(infer_constraints(
                     mapped.args[i], instance.args[i], self.direction))
                 res.extend(infer_constraints(
                     mapped.args[i], instance.args[i], neg_op(self.direction)))
             return res
         elif (self.direction == SUPERTYPE_OF and
                 instance.type.has_base(template.type.fullname())):
             mapped = map_instance_to_supertype(instance, template.type)
             for j in range(len(template.args)):
                 # The constraints for generic type parameters are
                 # invariant.
                 res.extend(infer_constraints(
                     template.args[j], mapped.args[j], self.direction))
                 res.extend(infer_constraints(
                     template.args[j], mapped.args[j], neg_op(self.direction)))
             return res
         if (template.type.is_protocol and self.direction == SUPERTYPE_OF and
                 # We avoid infinite recursion for structural subtypes by checking
                 # whether this type already appeared in the inference chain.
                 # This is a conservative way break the inference cycles.
                 # It never produces any "false" constraints but gives up soon
                 # on purely structural inference cycles, see #3829.
                 not any(is_same_type(template, t) for t in template.type.inferring) and
                 mypy.subtypes.is_subtype(instance, erase_typevars(template))):
             template.type.inferring.append(template)
             self.infer_constraints_from_protocol_members(res, instance, template,
                                                          original_actual, template)
             template.type.inferring.pop()
             return res
         elif (instance.type.is_protocol and self.direction == SUBTYPE_OF and
               # We avoid infinite recursion for structural subtypes also here.
               not any(is_same_type(instance, i) for i in instance.type.inferring) and
               mypy.subtypes.is_subtype(erase_typevars(template), instance)):
             instance.type.inferring.append(instance)
             self.infer_constraints_from_protocol_members(res, instance, template,
                                                          template, instance)
             instance.type.inferring.pop()
             return res
     if isinstance(actual, AnyType):
         # IDEA: Include both ways, i.e. add negation as well?
         return self.infer_against_any(template.args, actual)
     if (isinstance(actual, TupleType) and
         (is_named_instance(template, 'typing.Iterable') or
          is_named_instance(template, 'typing.Container') or
          is_named_instance(template, 'typing.Sequence') or
          is_named_instance(template, 'typing.Reversible'))
             and self.direction == SUPERTYPE_OF):
         for item in actual.items:
             cb = infer_constraints(template.args[0], item, SUPERTYPE_OF)
             res.extend(cb)
         return res
     elif isinstance(actual, TupleType) and self.direction == SUPERTYPE_OF:
         return infer_constraints(template, actual.fallback, self.direction)
     else:
         return []
Beispiel #43
0
def is_float(typ: Type):
    return is_same_type(typ, float_type())
Beispiel #44
0
def apply_generic_arguments(callable: CallableType, orig_types: Sequence[Optional[Type]],
                            msg: MessageBuilder, context: Context,
                            skip_unsatisfied: bool = False) -> CallableType:
    """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.

    If `skip_unsatisfied` is True, then just skip the types that don't satisfy type variable
    bound or constraints, instead of giving an error.
    """
    tvars = callable.variables
    assert len(tvars) == len(orig_types)
    # Check that inferred type variable values are compatible with allowed
    # values and bounds.  Also, promote subtype values to allowed values.
    types = list(orig_types)
    for i, type in enumerate(types):
        assert not isinstance(type, PartialType), "Internal error: must never apply partial type"
        values = callable.variables[i].values
        if type is None:
            continue
        if values:
            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
            matching = []
            for value in values:
                if mypy.subtypes.is_subtype(type, value):
                    matching.append(value)
            if matching:
                best = matching[0]
                # If there are more than one matching value, we select the narrowest
                for match in matching[1:]:
                    if mypy.subtypes.is_subtype(match, best):
                        best = match
                types[i] = best
            else:
                if skip_unsatisfied:
                    types[i] = None
                else:
                    msg.incompatible_typevar_value(callable, type, callable.variables[i].name,
                                                   context)
        else:
            upper_bound = callable.variables[i].upper_bound
            if not mypy.subtypes.is_subtype(type, upper_bound):
                if skip_unsatisfied:
                    types[i] = None
                else:
                    msg.incompatible_typevar_value(callable, type, callable.variables[i].name,
                                                   context)

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

    # 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 #45
0
def is_object(typ: Type):
    return is_same_type(typ, API.named_type('builtins.object'))
Beispiel #46
0
def is_protocol_implementation(left: Instance, right: Instance,
                               proper_subtype: bool = False) -> bool:
    """Check whether 'left' implements the protocol 'right'.

    If 'proper_subtype' is True, then check for a proper subtype.
    Treat recursive protocols by using the 'assuming' structural subtype matrix
    (in sparse representation, i.e. as a list of pairs (subtype, supertype)),
    see also comment in nodes.TypeInfo. When we enter a check for classes
    (A, P), defined as following::

      class P(Protocol):
          def f(self) -> P: ...
      class A:
          def f(self) -> A: ...

    this results in A being a subtype of P without infinite recursion.
    On every false result, we pop the assumption, thus avoiding an infinite recursion
    as well.
    """
    assert right.type.is_protocol
    assuming = right.type.assuming_proper if proper_subtype else right.type.assuming
    for (l, r) in reversed(assuming):
        if sametypes.is_same_type(l, left) and sametypes.is_same_type(r, right):
            return True
    with pop_on_exit(assuming, left, right):
        for member in right.type.protocol_members:
            # nominal subtyping currently ignores '__init__' and '__new__' signatures
            if member in ('__init__', '__new__'):
                continue
            # The third argument below indicates to what self type is bound.
            # We always bind self to the subtype. (Similarly to nominal types).
            supertype = find_member(member, right, left)
            assert supertype is not None
            subtype = find_member(member, left, left)
            # Useful for debugging:
            # print(member, 'of', left, 'has type', subtype)
            # print(member, 'of', right, 'has type', supertype)
            if not subtype:
                return False
            if not proper_subtype:
                # Nominal check currently ignores arg names
                is_compat = is_subtype(subtype, supertype, ignore_pos_arg_names=True)
            else:
                is_compat = is_proper_subtype(subtype, supertype)
            if not is_compat:
                return False
            if isinstance(subtype, NoneTyp) and isinstance(supertype, CallableType):
                # We want __hash__ = None idiom to work even without --strict-optional
                return False
            subflags = get_member_flags(member, left.type)
            superflags = get_member_flags(member, right.type)
            if IS_SETTABLE in superflags:
                # Check opposite direction for settable attributes.
                if not is_subtype(supertype, subtype):
                    return False
            if (IS_CLASSVAR in subflags) != (IS_CLASSVAR in superflags):
                return False
            if IS_SETTABLE in superflags and IS_SETTABLE not in subflags:
                return False
            # This rule is copied from nominal check in checker.py
            if IS_CLASS_OR_STATIC in superflags and IS_CLASS_OR_STATIC not in subflags:
                return False
    right.type.record_subtype_cache_entry(left, right, proper_subtype)
    return True
Beispiel #47
0
def is_same_constraint(c1: Constraint, c2: Constraint) -> bool:
    return (c1.type_var == c2.type_var
            and c1.op == c2.op
            and is_same_type(c1.target, c2.target))
Beispiel #48
0
def apply_generic_arguments(callable: CallableType,
                            orig_types: Sequence[Optional[Type]],
                            msg: MessageBuilder,
                            context: Context) -> CallableType:
    """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
    assert len(tvars) == len(orig_types)
    # Check that inferred type variable values are compatible with allowed
    # values and bounds.  Also, promote subtype values to allowed values.
    types = list(orig_types)
    for i, type in enumerate(types):
        assert not isinstance(
            type, PartialType), "Internal error: must never apply partial type"
        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, type,
                                               callable.variables[i].name,
                                               context)
        upper_bound = callable.variables[i].upper_bound
        if type and not mypy.subtypes.is_subtype(type, upper_bound):
            msg.incompatible_typevar_value(callable, type,
                                           callable.variables[i].name, context)

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

    # 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 #49
0
 def visit_instance(self, template: Instance) -> List[Constraint]:
     original_actual = actual = self.actual
     res = []  # type: List[Constraint]
     if isinstance(actual, (CallableType, Overloaded)) and template.type.is_protocol:
         if template.type.protocol_members == ['__call__']:
             # Special case: a generic callback protocol
             if not any(is_same_type(template, t) for t in template.type.inferring):
                 template.type.inferring.append(template)
                 call = mypy.subtypes.find_member('__call__', template, actual)
                 assert call is not None
                 if mypy.subtypes.is_subtype(actual, erase_typevars(call)):
                     subres = infer_constraints(call, actual, self.direction)
                     res.extend(subres)
                 template.type.inferring.pop()
                 return res
     if isinstance(actual, CallableType) and actual.fallback is not None:
         actual = actual.fallback
     if isinstance(actual, Overloaded) and actual.fallback is not None:
         actual = actual.fallback
     if isinstance(actual, TypedDictType):
         actual = actual.as_anonymous().fallback
     if isinstance(actual, Instance):
         instance = actual
         erased = erase_typevars(template)
         assert isinstance(erased, Instance)
         # We always try nominal inference if possible,
         # it is much faster than the structural one.
         if (self.direction == SUBTYPE_OF and
                 template.type.has_base(instance.type.fullname())):
             mapped = map_instance_to_supertype(template, instance.type)
             tvars = mapped.type.defn.type_vars
             for i in range(len(instance.args)):
                 # The constraints for generic type parameters depend on variance.
                 # Include constraints from both directions if invariant.
                 if tvars[i].variance != CONTRAVARIANT:
                     res.extend(infer_constraints(
                         mapped.args[i], instance.args[i], self.direction))
                 if tvars[i].variance != COVARIANT:
                     res.extend(infer_constraints(
                         mapped.args[i], instance.args[i], neg_op(self.direction)))
             return res
         elif (self.direction == SUPERTYPE_OF and
                 instance.type.has_base(template.type.fullname())):
             mapped = map_instance_to_supertype(instance, template.type)
             tvars = template.type.defn.type_vars
             for j in range(len(template.args)):
                 # The constraints for generic type parameters depend on variance.
                 # Include constraints from both directions if invariant.
                 if tvars[j].variance != CONTRAVARIANT:
                     res.extend(infer_constraints(
                         template.args[j], mapped.args[j], self.direction))
                 if tvars[j].variance != COVARIANT:
                     res.extend(infer_constraints(
                         template.args[j], mapped.args[j], neg_op(self.direction)))
             return res
         if (template.type.is_protocol and self.direction == SUPERTYPE_OF and
                 # We avoid infinite recursion for structural subtypes by checking
                 # whether this type already appeared in the inference chain.
                 # This is a conservative way break the inference cycles.
                 # It never produces any "false" constraints but gives up soon
                 # on purely structural inference cycles, see #3829.
                 # Note that we use is_protocol_implementation instead of is_subtype
                 # because some type may be considered a subtype of a protocol
                 # due to _promote, but still not implement the protocol.
                 not any(is_same_type(template, t) for t in template.type.inferring) and
                 mypy.subtypes.is_protocol_implementation(instance, erased)):
             template.type.inferring.append(template)
             self.infer_constraints_from_protocol_members(res, instance, template,
                                                          original_actual, template)
             template.type.inferring.pop()
             return res
         elif (instance.type.is_protocol and self.direction == SUBTYPE_OF and
               # We avoid infinite recursion for structural subtypes also here.
               not any(is_same_type(instance, i) for i in instance.type.inferring) and
               mypy.subtypes.is_protocol_implementation(erased, instance)):
             instance.type.inferring.append(instance)
             self.infer_constraints_from_protocol_members(res, instance, template,
                                                          template, instance)
             instance.type.inferring.pop()
             return res
     if isinstance(actual, AnyType):
         # IDEA: Include both ways, i.e. add negation as well?
         return self.infer_against_any(template.args, actual)
     if (isinstance(actual, TupleType) and
         (is_named_instance(template, 'typing.Iterable') or
          is_named_instance(template, 'typing.Container') or
          is_named_instance(template, 'typing.Sequence') or
          is_named_instance(template, 'typing.Reversible'))
             and self.direction == SUPERTYPE_OF):
         for item in actual.items:
             cb = infer_constraints(template.args[0], item, SUPERTYPE_OF)
             res.extend(cb)
         return res
     elif isinstance(actual, TupleType) and self.direction == SUPERTYPE_OF:
         return infer_constraints(template, actual.fallback, self.direction)
     else:
         return []
Beispiel #50
0
def is_none(typ: Type):
    return is_same_type(typ, NoneTyp())
Beispiel #51
0
def _oas_handler_analyzer(
    specifications: Mapping[Path, oas_model.OASSpecification],
    f_ctx: FunctionContext,
) -> Type:
    # TODO(kornicameister) make `OASSpectification.operations` a mapping
    # to allow easy access

    oas_handler = f_ctx.arg_types[0][0]

    assert isinstance(oas_handler, CallableType)
    assert oas_handler.definition

    f_name = oas_handler.name
    oas_operation = _get_oas_operation(
        oas_handler.definition.fullname,
        specifications,
    )

    if oas_operation is None:
        return errors.not_oas_handler(
            msg=f'{f_name} is not OAS operation',
            ctx=f_ctx,
            line_number=oas_handler.definition.line,
        )

    signature: Dict[str, Type] = {
        k: v
        for k, v in dict(zip(
            oas_handler.arg_names,
            oas_handler.arg_types,
        ), ).items() if k is not None
    }.copy()
    sorted(signature)

    for oas_param, f_param in map(
            lambda ofp: (ofp, handler_model.get_f_param(ofp.name)),
            oas.operation_filter_parameters(
                oas_operation,
                'path',
                'query',
            ),
    ):
        handler_arg_type: Optional[Type] = signature.pop(f_param, None)
        handler_arg_default_value = _get_default_value(f_param, oas_handler)
        oas_default_values = oas.parameter_default_values(oas_param)

        if handler_arg_type is None:
            # log the fact that argument is not there
            _oas_handler_msg(
                f_ctx.api.msg.fail,
                f_ctx,
                (
                    errors.ERROR_INVALID_OAS_ARG,
                    (f'{f_name} does not declare OAS {oas.parameter_in(oas_param)} '
                     f'{oas_param.name}::{f_param} argument'),
                ),
            )
            continue

        oas_param_type = transform_parameter_to_type(
            oas_param,
            get_proper_type(handler_arg_type),
            handler_arg_default_value,
            f_ctx,
        )
        if not any((
                is_same_type(handler_arg_type, oas_param_type),
                is_equivalent_type(handler_arg_type, oas_param_type),
        )):
            errors.invalid_argument(
                msg=(f'[{f_name}({f_param} -> {oas_param.name})] '
                     f'expected {format_type(oas_param_type)}, '
                     f'but got {format_type(handler_arg_type)}'),
                ctx=f_ctx,
                line_number=handler_arg_type.line,
            )
            continue

        # validate default value
        if handler_arg_default_value is not _ARG_NO_DEFAULT_VALUE_MARKER:
            if len(oas_default_values):
                default_matches = handler_arg_default_value in oas_default_values
                if not default_matches:
                    errors.invalid_default_value(
                        msg=
                        (f'[{f_name}({f_param} -> {oas_param.name})] '
                         f'Incorrect default value. '
                         f'Expected {",".join(map(str, oas_default_values))} '
                         f'but got {handler_arg_default_value}'),
                        ctx=f_ctx,
                        line_number=handler_arg_type.line,
                    )
                    continue
            elif not isinstance(handler_arg_default_value, type(None)):
                errors.default_value_not_in_oas(
                    msg=
                    (f'[{f_name}({f_param} -> {oas_param.name})] '
                     f'OAS does not define a default value. '
                     f'If you want "{handler_arg_default_value}" to be '
                     f'consistent default value, it should be declared in OAS too. '
                     ),
                    ctx=f_ctx,
                    line_number=handler_arg_type.line,
                )
        elif oas_default_values:
            errors.invalid_default_value(
                msg=
                (f'[{f_name}({f_param} -> {oas_param.name})] OAS '
                 f'defines "{",".join(map(str, oas_default_values))}" as a '
                 f'default value. It should be reflected in argument default value.'
                 ),
                ctx=f_ctx,
                line_number=handler_arg_type.line,
            )
            continue

    if signature:
        # unconsumed handler arguments
        ...

    return f_ctx.default_return_type
Beispiel #52
0
def has_no_typevars(typ: Type) -> bool:
    return is_same_type(typ, erase_typevars(typ))
Beispiel #53
0
def has_no_typevars(typ: Type) -> bool:
    return is_same_type(typ, erase_typevars(typ))
Beispiel #54
0
def is_same_constraint(c1: Constraint, c2: Constraint) -> bool:
    return (c1.type_var == c2.type_var and c1.op == c2.op
            and is_same_type(c1.target, c2.target))
Beispiel #55
0
def is_protocol_implementation(left: Instance,
                               right: Instance,
                               proper_subtype: bool = False) -> bool:
    """Check whether 'left' implements the protocol 'right'.

    If 'proper_subtype' is True, then check for a proper subtype.
    Treat recursive protocols by using the 'assuming' structural subtype matrix
    (in sparse representation, i.e. as a list of pairs (subtype, supertype)),
    see also comment in nodes.TypeInfo. When we enter a check for classes
    (A, P), defined as following::

      class P(Protocol):
          def f(self) -> P: ...
      class A:
          def f(self) -> A: ...

    this results in A being a subtype of P without infinite recursion.
    On every false result, we pop the assumption, thus avoiding an infinite recursion
    as well.
    """
    assert right.type.is_protocol
    # We need to record this check to generate protocol fine-grained dependencies.
    TypeState.record_protocol_subtype_check(left.type, right.type)
    assuming = right.type.assuming_proper if proper_subtype else right.type.assuming
    for (l, r) in reversed(assuming):
        if sametypes.is_same_type(l, left) and sametypes.is_same_type(
                r, right):
            return True
    with pop_on_exit(assuming, left, right):
        for member in right.type.protocol_members:
            # nominal subtyping currently ignores '__init__' and '__new__' signatures
            if member in ('__init__', '__new__'):
                continue
            # The third argument below indicates to what self type is bound.
            # We always bind self to the subtype. (Similarly to nominal types).
            supertype = find_member(member, right, left)
            assert supertype is not None
            subtype = find_member(member, left, left)
            # Useful for debugging:
            # print(member, 'of', left, 'has type', subtype)
            # print(member, 'of', right, 'has type', supertype)
            if not subtype:
                return False
            if not proper_subtype:
                # Nominal check currently ignores arg names
                is_compat = is_subtype(subtype,
                                       supertype,
                                       ignore_pos_arg_names=True)
            else:
                is_compat = is_proper_subtype(subtype, supertype)
            if not is_compat:
                return False
            if isinstance(subtype, NoneTyp) and isinstance(
                    supertype, CallableType):
                # We want __hash__ = None idiom to work even without --strict-optional
                return False
            subflags = get_member_flags(member, left.type)
            superflags = get_member_flags(member, right.type)
            if IS_SETTABLE in superflags:
                # Check opposite direction for settable attributes.
                if not is_subtype(supertype, subtype):
                    return False
            if (IS_CLASSVAR in subflags) != (IS_CLASSVAR in superflags):
                return False
            if IS_SETTABLE in superflags and IS_SETTABLE not in subflags:
                return False
            # This rule is copied from nominal check in checker.py
            if IS_CLASS_OR_STATIC in superflags and IS_CLASS_OR_STATIC not in subflags:
                return False
    if proper_subtype:
        TypeState.record_proper_subtype_cache_entry(left, right)
    else:
        TypeState.record_subtype_cache_entry(left, right)
    return True