Пример #1
0
def is_special_target(right: ProperType) -> bool:
    """Whitelist some special cases for use in isinstance() with improper types."""
    if isinstance(right, CallableType) and right.is_type_obj():
        if right.type_object().fullname() == 'builtins.tuple':
            # Used with Union[Type, Tuple[Type, ...]].
            return True
        if right.type_object().fullname() in ('mypy.types.Type',
                                              'mypy.types.ProperType',
                                              'mypy.types.TypeAliasType'):
            # Special case: things like assert isinstance(typ, ProperType) are always OK.
            return True
        if right.type_object().fullname() in ('mypy.types.UnboundType',
                                              'mypy.types.TypeVarType',
                                              'mypy.types.RawExpressionType',
                                              'mypy.types.EllipsisType',
                                              'mypy.types.StarType',
                                              'mypy.types.TypeList',
                                              'mypy.types.CallableArgument',
                                              'mypy.types.PartialType',
                                              'mypy.types.ErasedType'):
            # Special case: these are not valid targets for a type alias and thus safe.
            # TODO: introduce a SyntheticType base to simplify this?
            return True
    elif isinstance(right, TupleType):
        return all(is_special_target(t) for t in get_proper_types(right.items))
    return False
Пример #2
0
def is_dangerous_target(typ: ProperType) -> bool:
    """Is this a dangerous target (right argument) for an isinstance() check?"""
    if isinstance(typ, TupleType):
        return any(is_dangerous_target(get_proper_type(t)) for t in typ.items)
    if isinstance(typ, CallableType) and typ.is_type_obj():
        return typ.type_object().has_base('mypy.types.Type')
    return False
Пример #3
0
def add_class_tvars(t: ProperType, itype: Instance, isuper: Optional[Instance],
                    is_classmethod: bool, builtin_type: Callable[[str],
                                                                 Instance],
                    original_type: Type) -> Type:
    """Instantiate type variables during analyze_class_attribute_access,
    e.g T and Q in the following:

    class A(Generic[T]):
        @classmethod
        def foo(cls: Type[Q]) -> Tuple[T, Q]: ...

    class B(A[str]): pass

    B.foo()

    original_type is the value of the type B in the expression B.foo()
    """
    # TODO: verify consistency between Q and T
    info = itype.type  # type: TypeInfo
    if is_classmethod:
        assert isuper is not None
        t = expand_type_by_instance(t, isuper)
    # We add class type variables if the class method is accessed on class object
    # without applied type arguments, this matches the behavior of __init__().
    # For example (continuing the example in docstring):
    #     A       # The type of callable is def [T] () -> A[T], _not_ def () -> A[Any]
    #     A[int]  # The type of callable is def () -> A[int]
    # and
    #     A.foo       # The type is generic def [T] () -> Tuple[T, A[T]]
    #     A[int].foo  # The type is non-generic def () -> Tuple[int, A[int]]
    #
    # This behaviour is useful for defining alternative constructors for generic classes.
    # To achieve such behaviour, we add the class type variables that are still free
    # (i.e. appear in the return type of the class object on which the method was accessed).
    free_ids = {t.id for t in itype.args if isinstance(t, TypeVarType)}

    if isinstance(t, CallableType):
        # NOTE: in practice either all or none of the variables are free, since
        # visit_type_application() will detect any type argument count mismatch and apply
        # a correct number of Anys.
        tvars = [
            TypeVarDef(n, n, i + 1, [], builtin_type('builtins.object'),
                       tv.variance)
            for (i,
                 n), tv in zip(enumerate(info.type_vars), info.defn.type_vars)
            # use 'is' to avoid id clashes with unrelated variables
            if any(tv.id is id for id in free_ids)
        ]
        if is_classmethod:
            t = bind_self(t, original_type, is_classmethod=True)
        return t.copy_modified(variables=tvars + t.variables)
    elif isinstance(t, Overloaded):
        return Overloaded([
            cast(
                CallableType,
                add_class_tvars(item, itype, isuper, is_classmethod,
                                builtin_type, original_type))
            for item in t.items()
        ])
    return t
Пример #4
0
def add_class_tvars(t: ProperType,
                    itype: Instance,
                    isuper: Optional[Instance],
                    is_classmethod: bool,
                    builtin_type: Callable[[str], Instance],
                    original_type: Type,
                    original_vars: Optional[List[TypeVarDef]] = None) -> Type:
    """Instantiate type variables during analyze_class_attribute_access,
    e.g T and Q in the following:

    class A(Generic[T]):
        @classmethod
        def foo(cls: Type[Q]) -> Tuple[T, Q]: ...

    class B(A[str]): pass

    B.foo()

    original_type is the value of the type B in the expression B.foo() or the corresponding
    component in case if a union (this is used to bind the self-types); original_vars are type
    variables of the class callable on which the method was accessed.
    """
    # TODO: verify consistency between Q and T
    if is_classmethod:
        assert isuper is not None
        t = get_proper_type(expand_type_by_instance(t, isuper))
    # We add class type variables if the class method is accessed on class object
    # without applied type arguments, this matches the behavior of __init__().
    # For example (continuing the example in docstring):
    #     A       # The type of callable is def [T] () -> A[T], _not_ def () -> A[Any]
    #     A[int]  # The type of callable is def () -> A[int]
    # and
    #     A.foo       # The type is generic def [T] () -> Tuple[T, A[T]]
    #     A[int].foo  # The type is non-generic def () -> Tuple[int, A[int]]
    #
    # This behaviour is useful for defining alternative constructors for generic classes.
    # To achieve such behaviour, we add the class type variables that are still free
    # (i.e. appear in the return type of the class object on which the method was accessed).
    if isinstance(t, CallableType):
        tvars = original_vars if original_vars is not None else []
        if is_classmethod:
            t = bind_self(t, original_type, is_classmethod=True)
        return t.copy_modified(variables=tvars + t.variables)
    elif isinstance(t, Overloaded):
        return Overloaded([
            cast(
                CallableType,
                add_class_tvars(item,
                                itype,
                                isuper,
                                is_classmethod,
                                builtin_type,
                                original_type,
                                original_vars=original_vars))
            for item in t.items()
        ])
    return t
Пример #5
0
def add_class_tvars(t: ProperType, isuper: Optional[Instance],
                    is_classmethod: bool,
                    original_type: Type,
                    original_vars: Optional[Sequence[TypeVarLikeDef]] = None) -> Type:
    """Instantiate type variables during analyze_class_attribute_access,
    e.g T and Q in the following:

    class A(Generic[T]):
        @classmethod
        def foo(cls: Type[Q]) -> Tuple[T, Q]: ...

    class B(A[str]): pass
    B.foo()

    Args:
        t: Declared type of the method (or property)
        isuper: Current instance mapped to the superclass where method was defined, this
            is usually done by map_instance_to_supertype()
        is_classmethod: True if this method is decorated with @classmethod
        original_type: The value of the type B in the expression B.foo() or the corresponding
            component in case of a union (this is used to bind the self-types)
        original_vars: Type variables of the class callable on which the method was accessed
    Returns:
        Expanded method type with added type variables (when needed).
    """
    # TODO: verify consistency between Q and T

    # We add class type variables if the class method is accessed on class object
    # without applied type arguments, this matches the behavior of __init__().
    # For example (continuing the example in docstring):
    #     A       # The type of callable is def [T] () -> A[T], _not_ def () -> A[Any]
    #     A[int]  # The type of callable is def () -> A[int]
    # and
    #     A.foo       # The type is generic def [T] () -> Tuple[T, A[T]]
    #     A[int].foo  # The type is non-generic def () -> Tuple[int, A[int]]
    #
    # This behaviour is useful for defining alternative constructors for generic classes.
    # To achieve such behaviour, we add the class type variables that are still free
    # (i.e. appear in the return type of the class object on which the method was accessed).
    if isinstance(t, CallableType):
        tvars = original_vars if original_vars is not None else []
        if is_classmethod:
            t = freshen_function_type_vars(t)
            t = bind_self(t, original_type, is_classmethod=True)
            assert isuper is not None
            t = cast(CallableType, expand_type_by_instance(t, isuper))
            freeze_type_vars(t)
        return t.copy_modified(variables=list(tvars) + list(t.variables))
    elif isinstance(t, Overloaded):
        return Overloaded([cast(CallableType, add_class_tvars(item, isuper,
                                                              is_classmethod, original_type,
                                                              original_vars=original_vars))
                           for item in t.items()])
    if isuper is not None:
        t = cast(ProperType, expand_type_by_instance(t, isuper))
    return t
Пример #6
0
def get_typed_dict_type(
    ctx: FunctionContext,
    handler_arg_type: ProperType,
    oas_type: oas_model.OASObjectType,
) -> TypedDictType:

    if isinstance(handler_arg_type, UnionType):
        td_type_fallback = next(
            try_getting_instance_fallback(get_proper_type(x))
            for x in handler_arg_type.relevant_items())
    else:
        td_type_fallback = try_getting_instance_fallback(handler_arg_type)

    assert td_type_fallback is not None

    return TypedDictType(
        items=OrderedDict({
            oas_prop_name: transform_oas_type(oas_prop_type, handler_arg_type,
                                              ctx)
            for oas_prop_name, oas_prop_type in oas_type.properties.items()
        }),
        required_keys=oas_type.required,
        fallback=td_type_fallback,
        line=td_type_fallback.line,
        column=td_type_fallback.column,
    )
Пример #7
0
def freeze_type_vars(member_type: ProperType) -> None:
    if isinstance(member_type, CallableType):
        for v in member_type.variables:
            v.id.meta_level = 0
    if isinstance(member_type, Overloaded):
        for it in member_type.items():
            for v in it.variables:
                v.id.meta_level = 0
Пример #8
0
def copy_type(t: ProperType) -> ProperType:
    """Create a shallow copy of a type.

    This can be used to mutate the copy with truthiness information.

    Classes compiled with mypyc don't support copy.copy(), so we need
    a custom implementation.
    """
    return t.accept(TypeShallowCopier())
Пример #9
0
 def _type_object_overlap(left: ProperType, right: ProperType) -> bool:
     """Special cases for type object types overlaps."""
     # TODO: these checks are a bit in gray area, adjust if they cause problems.
     # 1. Type[C] vs Callable[..., C], where the latter is class object.
     if isinstance(left, TypeType) and isinstance(right, CallableType) and right.is_type_obj():
         return _is_overlapping_types(left.item, right.ret_type)
     # 2. Type[C] vs Meta, where Meta is a metaclass for C.
     if (isinstance(left, TypeType) and isinstance(left.item, Instance) and
             isinstance(right, Instance)):
         left_meta = left.item.type.metaclass_type
         if left_meta is not None:
             return _is_overlapping_types(left_meta, right)
         # builtins.type (default metaclass) overlaps with all metaclasses
         return right.type.has_base('builtins.type')
     # 3. Callable[..., C] vs Meta is considered below, when we switch to fallbacks.
     return False
Пример #10
0
 def add_operator_method_dependency_for_type(self, typ: ProperType, method: str) -> None:
     # Note that operator methods can't be (non-metaclass) methods of type objects
     # (that is, TypeType objects or Callables representing a type).
     if isinstance(typ, TypeVarType):
         typ = get_proper_type(typ.upper_bound)
     if isinstance(typ, TupleType):
         typ = typ.partial_fallback
     if isinstance(typ, Instance):
         trigger = make_trigger(typ.type.fullname + '.' + method)
         self.add_dependency(trigger)
     elif isinstance(typ, UnionType):
         for item in typ.items:
             self.add_operator_method_dependency_for_type(get_proper_type(item), method)
     elif isinstance(typ, FunctionLike) and typ.is_type_obj():
         self.add_operator_method_dependency_for_type(typ.fallback, method)
     elif isinstance(typ, TypeType):
         if isinstance(typ.item, Instance) and typ.item.type.metaclass_type is not None:
             self.add_operator_method_dependency_for_type(typ.item.type.metaclass_type, method)
Пример #11
0
def adjust_tuple(left: ProperType, r: ProperType) -> Optional[TupleType]:
    """Find out if `left` is a Tuple[A, ...], and adjust its length to `right`"""
    if isinstance(left, Instance) and left.type.fullname() == 'builtins.tuple':
        n = r.length() if isinstance(r, TupleType) else 1
        return TupleType([left.args[0]] * n, left)
    return None
Пример #12
0
 def copy_common(self, t: ProperType, t2: ProperType) -> ProperType:
     t2.line = t.line
     t2.column = t.column
     t2.can_be_false = t.can_be_false
     t2.can_be_true = t.can_be_true
     return t2
Пример #13
0
def is_enum_overlapping_union(x: ProperType, y: ProperType) -> bool:
    """Return True if x is an Enum, and y is an Union with at least one Literal from x"""
    return (isinstance(x, Instance) and x.type.is_enum
            and isinstance(y, UnionType) and any(
                isinstance(p, LiteralType) and x.type == p.fallback.type
                for p in (get_proper_type(z) for z in y.relevant_items())))