Пример #1
0
def is_overlapping_erased_types(left: Type,
                                right: Type,
                                *,
                                ignore_promotions: bool = False) -> bool:
    """The same as 'is_overlapping_erased_types', except the types are erased first."""
    return is_overlapping_types(erase_type(left),
                                erase_type(right),
                                ignore_promotions=ignore_promotions,
                                prohibit_none_typevar_overlap=True)
Пример #2
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,
    ]))
Пример #3
0
def restrict_subtype_away(t: Type, s: Type) -> Type:
    """Return t minus s.

    If we can't determine a precise result, return a supertype of the
    ideal result (just t is a valid result).

    This is used for type inference of runtime type checks such as
    isinstance.

    Currently this just removes elements of a union type.
    """
    if isinstance(t, UnionType):
        # Since runtime type checks will ignore type arguments, erase the types.
        erased_s = erase_type(s)
        new_items = [item for item in t.relevant_items()
                     if (not is_proper_subtype(erase_type(item), erased_s)
                         or isinstance(item, AnyType))]
        return UnionType.make_union(new_items)
    else:
        return t
Пример #4
0
    def format(self, typ: Type, verbosity: int = 0) -> str:
        """Convert a type to a relatively short string that is suitable for error messages.

        Mostly behave like format_simple below, but never return an empty string.
        """
        s = self.format_simple(typ, verbosity)
        if s != '':
            # If format_simple returns a non-trivial result, use that.
            return s
        elif isinstance(typ, FunctionLike):
            func = typ
            if func.is_type_obj():
                # The type of a type object type can be derived from the
                # return type (this always works).
                return self.format(
                    TypeType.make_normalized(
                        erase_type(func.items()[0].ret_type)), verbosity)
            elif isinstance(func, CallableType):
                return_type = strip_quotes(self.format(func.ret_type))
                if func.is_ellipsis_args:
                    return 'Callable[..., {}]'.format(return_type)
                arg_strings = []
                for arg_name, arg_type, arg_kind in zip(
                        func.arg_names, func.arg_types, func.arg_kinds):
                    if (arg_kind == ARG_POS and arg_name is None or
                            verbosity == 0 and arg_kind in (ARG_POS, ARG_OPT)):

                        arg_strings.append(
                            strip_quotes(
                                self.format(arg_type,
                                            verbosity=max(verbosity - 1, 0))))
                    else:
                        constructor = ARG_CONSTRUCTOR_NAMES[arg_kind]
                        if arg_kind in (ARG_STAR,
                                        ARG_STAR2) or arg_name is None:
                            arg_strings.append("{}({})".format(
                                constructor,
                                strip_quotes(self.format(arg_type))))
                        else:
                            arg_strings.append("{}({}, {})".format(
                                constructor,
                                strip_quotes(self.format(arg_type)),
                                repr(arg_name)))

                return 'Callable[[{}], {}]'.format(", ".join(arg_strings),
                                                   return_type)
            else:
                # Use a simple representation for function types; proper
                # function types may result in long and difficult-to-read
                # error messages.
                return 'overloaded function'
        else:
            # Default case; we simply have to return something meaningful here.
            return 'object'
Пример #5
0
def restrict_subtype_away(t: Type, s: Type) -> Type:
    """Return t minus s.

    If we can't determine a precise result, return a supertype of the
    ideal result (just t is a valid result).

    This is used for type inference of runtime type checks such as
    isinstance.

    Currently this just removes elements of a union type.
    """
    if isinstance(t, UnionType):
        # Since runtime type checks will ignore type arguments, erase the types.
        erased_s = erase_type(s)
        # TODO: Implement more robust support for runtime isinstance() checks,
        # see issue #3827
        new_items = [item for item in t.relevant_items()
                     if (not (is_proper_subtype(erase_type(item), erased_s) or
                              is_proper_subtype(item, erased_s))
                         or isinstance(item, AnyType))]
        return UnionType.make_union(new_items)
    else:
        return t
Пример #6
0
 def assert_erase(self, orig, result):
     assert_equal(str(erase_type(orig)), str(result))
Пример #7
0
 def assert_erase(self, orig: Type, result: Type) -> None:
     assert_equal(str(erase_type(orig)), str(result))
Пример #8
0
 def assert_erase(self, orig: Type, result: Type) -> None:
     assert_equal(str(erase_type(orig)), str(result))
Пример #9
0
def is_overlapping_erased_types(left: Type, right: Type, *,
                                ignore_promotions: bool = False) -> bool:
    """The same as 'is_overlapping_erased_types', except the types are erased first."""
    return is_overlapping_types(erase_type(left), erase_type(right),
                                ignore_promotions=ignore_promotions,
                                prohibit_none_typevar_overlap=True)
Пример #10
0
 def assert_erase(self, orig, result):
     assert_equal(str(erase_type(orig)), str(result))
Пример #11
0
 def assert_erase(self, orig, result):
     assert_equal(str(erase_type(orig, self.fx.basic)), str(result))
Пример #12
0
 def assert_erase(self, orig, result):
     assert_equal(str(erase_type(orig, self.fx.basic)), str(result))