Exemplo n.º 1
0
def _autoconvertible_to_cdata(tp: Type, api: 'mypy.plugin.CheckerPluginInterface') -> Type:
    """Get a type that is compatible with all types that can be implicitly converted to the given
    CData type.

    Examples:
    * c_int -> Union[c_int, int]
    * c_char_p -> Union[c_char_p, bytes, int, NoneType]
    * MyStructure -> MyStructure
    """
    allowed_types = []
    # If tp is a union, we allow all types that are convertible to at least one of the union
    # items. This is not quite correct - strictly speaking, only types convertible to *all* of the
    # union items should be allowed. This may be worth changing in the future, but the more
    # correct algorithm could be too strict to be useful.
    for t in union_items(tp):
        # Every type can be converted from itself (obviously).
        allowed_types.append(t)
        if isinstance(t, Instance):
            unboxed = _find_simplecdata_base_arg(t, api)
            if unboxed is not None:
                # If _SimpleCData appears in tp's (direct or indirect) bases, its type argument
                # specifies the type's "unboxed" version, which can always be converted back to
                # the original "boxed" type.
                allowed_types.append(unboxed)

                if t.type.has_base('ctypes._PointerLike'):
                    # Pointer-like _SimpleCData subclasses can also be converted from
                    # an int or None.
                    allowed_types.append(api.named_generic_type('builtins.int', []))
                    allowed_types.append(NoneTyp())

    return UnionType.make_simplified_union(allowed_types)
Exemplo n.º 2
0
def make_optional_type(t: Type) -> Type:
    """Return the type corresponding to Optional[t].

    Note that we can't use normal union simplification, since this function
    is called during semantic analysis and simplification only works during
    type checking.
    """
    if isinstance(t, NoneTyp):
        return t
    elif isinstance(t, UnionType):
        items = [item for item in union_items(t)
                 if not isinstance(item, NoneTyp)]
        return UnionType(items + [NoneTyp()], t.line, t.column)
    else:
        return UnionType([t, NoneTyp()], t.line, t.column)
Exemplo n.º 3
0
def make_optional_type(t: Type) -> Type:
    """Return the type corresponding to Optional[t].

    Note that we can't use normal union simplification, since this function
    is called during semantic analysis and simplification only works during
    type checking.
    """
    if isinstance(t, NoneTyp):
        return t
    elif isinstance(t, UnionType):
        items = [
            item for item in union_items(t) if not isinstance(item, NoneTyp)
        ]
        return UnionType(items + [NoneTyp()], t.line, t.column)
    else:
        return UnionType([t, NoneTyp()], t.line, t.column)
Exemplo n.º 4
0
def array_raw_callback(ctx: 'mypy.plugin.AttributeContext') -> Type:
    """Callback to provide an accurate type for ctypes.Array.raw."""
    et = _get_array_element_type(ctx.type)
    if et is not None:
        types = []  # type: List[Type]
        for tp in union_items(et):
            if (isinstance(tp, AnyType) or isinstance(tp, Instance)
                    and tp.type.fullname == 'ctypes.c_char'):
                types.append(_get_bytes_type(ctx.api))
            else:
                ctx.api.msg.fail(
                    'Array attribute "raw" is only available'
                    ' with element type "c_char", not {}'.format(
                        format_type(et)), ctx.context)
        return make_simplified_union(types)
    return ctx.default_attr_type
Exemplo n.º 5
0
def array_raw_callback(ctx: 'mypy.plugin.AttributeContext') -> Type:
    """Callback to provide an accurate type for ctypes.Array.raw."""
    et = _get_array_element_type(ctx.type)
    if et is not None:
        types = []  # type: List[Type]
        for tp in union_items(et):
            if (isinstance(tp, AnyType)
                    or isinstance(tp, Instance) and tp.type.fullname() == 'ctypes.c_char'):
                types.append(_get_bytes_type(ctx.api))
            else:
                ctx.api.msg.fail(
                    'ctypes.Array attribute "raw" is only available'
                    ' with element type c_char, not "{}"'
                    .format(et),
                    ctx.context)
        return UnionType.make_simplified_union(types)
    return ctx.default_attr_type
Exemplo n.º 6
0
def array_value_callback(ctx: 'mypy.plugin.AttributeContext') -> Type:
    """Callback to provide an accurate type for ctypes.Array.value."""
    et = _get_array_element_type(ctx.type)
    if et is not None:
        types: List[Type] = []
        for tp in union_items(et):
            if isinstance(tp, AnyType):
                types.append(AnyType(TypeOfAny.from_another_any, source_any=tp))
            elif isinstance(tp, Instance) and tp.type.fullname == 'ctypes.c_char':
                types.append(_get_bytes_type(ctx.api))
            elif isinstance(tp, Instance) and tp.type.fullname == 'ctypes.c_wchar':
                types.append(_get_text_type(ctx.api))
            else:
                ctx.api.msg.fail(
                    'Array attribute "value" is only available'
                    ' with element type "c_char" or "c_wchar", not {}'
                    .format(format_type(et)), ctx.context)
        return make_simplified_union(types)
    return ctx.default_attr_type
Exemplo n.º 7
0
    def __init__(
        self,
        associated_type: MypyType,
        instance_type: MypyType,
        ctx: MethodContext,
    ) -> None:
        """
        Smart constructor for the metadata injector.

        It is smart, because it handles ``instance_type`` properly.
        It supports ``Instance`` and ``Union`` types.
        """
        self._associated_type = associated_type
        self._instance_types = union_items(instance_type)
        self._ctx = ctx

        # Why do we store added types in a mutable global state?
        # Because, these types are hard to replicate without the proper context.
        # So, we just keep them here. Based on usage, it is fine.
        self._added_types: List[Instance] = []