Beispiel #1
0
def analyze_class_attribute_access(itype: Instance,
                                   name: str,
                                   context: Context,
                                   is_lvalue: bool,
                                   builtin_type: Callable[[str], Instance],
                                   msg: MessageBuilder) -> Type:
    node = itype.type.get(name)
    if not node:
        if itype.type.fallback_to_any:
            return AnyType()
        return None

    is_decorated = isinstance(node.node, Decorator)
    is_method = is_decorated or isinstance(node.node, FuncDef)
    if is_lvalue:
        if is_method:
            msg.cant_assign_to_method(context)
        if isinstance(node.node, TypeInfo):
            msg.fail(messages.CANNOT_ASSIGN_TO_TYPE, context)

    if itype.type.is_enum and not (is_lvalue or is_decorated or is_method):
        return itype

    t = node.type
    if t:
        is_classmethod = is_decorated and cast(Decorator, node.node).func.is_class
        return add_class_tvars(t, itype.type, is_classmethod, builtin_type)
    elif isinstance(node.node, Var):
        msg.cannot_determine_type(name, context)
        return AnyType()

    if isinstance(node.node, TypeInfo):
        return type_object_type(cast(TypeInfo, node.node), builtin_type)

    return function_type(cast(FuncBase, node.node), builtin_type('builtins.function'))
Beispiel #2
0
def analyze_class_attribute_access(itype: Instance, name: str,
                                   context: Context, is_lvalue: bool,
                                   builtin_type: Callable[[str], Instance],
                                   msg: MessageBuilder) -> Type:
    node = itype.type.get(name)
    if not node:
        return None

    is_decorated = isinstance(node.node, Decorator)
    is_method = is_decorated or isinstance(node.node, FuncDef)
    if is_lvalue:
        if is_method:
            msg.cant_assign_to_method(context)
        if isinstance(node.node, TypeInfo):
            msg.fail(messages.CANNOT_ASSIGN_TO_TYPE, context)

    if itype.type.is_enum and not (is_lvalue or is_decorated or is_method):
        return itype

    t = node.type
    if t:
        is_classmethod = is_decorated and cast(Decorator,
                                               node.node).func.is_class
        return add_class_tvars(t, itype.type, is_classmethod, builtin_type)
    elif isinstance(node.node, Var):
        msg.cannot_determine_type(name, context)
        return AnyType()

    if isinstance(node.node, TypeInfo):
        return type_object_type(cast(TypeInfo, node.node), builtin_type)

    return function_type(cast(FuncBase, node.node),
                         builtin_type('builtins.function'))
Beispiel #3
0
def analyse_member_var_access(name: str, itype: Instance, info: TypeInfo,
                              node: Context, is_lvalue: bool, is_super: bool,
                              msg: MessageBuilder,
                              report_type: Type = None) -> Type:
    """Analyse attribute access that does not target a method.

    This is logically part of analyse_member_access and the arguments are
    similar.
    """
    # It was not a method. Try looking up a variable.
    v = lookup_member_var_or_accessor(info, name, is_lvalue)

    vv = v
    if isinstance(vv, Decorator):
        # The associated Var node of a decorator contains the type.
        v = vv.var

    if isinstance(v, Var):
        # Found a member variable.
        var = v
        itype = map_instance_to_supertype(itype, var.info)
        if var.type:
            t = expand_type_by_instance(var.type, itype)
            if var.is_initialized_in_class and isinstance(t, FunctionLike):
                if is_lvalue:
                    if var.is_property:
                        msg.read_only_property(name, info, node)
                    else:
                        msg.cant_assign_to_method(node)

                if not var.is_staticmethod:
                    # Class-level function objects and classmethods become bound
                    # methods: the former to the instance, the latter to the
                    # class.
                    functype = cast(FunctionLike, t)
                    check_method_type(functype, itype, node, msg)
                    signature = method_type(functype)
                    if var.is_property:
                        # A property cannot have an overloaded type => the cast
                        # is fine.
                        return cast(Callable, signature).ret_type
                    else:
                        return signature
            return t
        else:
            if not var.is_ready:
                msg.cannot_determine_type(var.name(), node)
            # Implicit 'Any' type.
            return AnyType()
    elif isinstance(v, FuncDef):
        assert False, "Did not expect a function"

    # Could not find the member.
    if is_super:
        msg.undefined_in_superclass(name, node)
        return AnyType()
    else:
        return msg.has_no_attr(report_type or itype, name, node)
Beispiel #4
0
def analyse_member_var_access(name: str,
                              itype: Instance,
                              info: TypeInfo,
                              node: Context,
                              is_lvalue: bool,
                              is_super: bool,
                              msg: MessageBuilder,
                              report_type: Type = None) -> Type:
    """Analyse attribute access that does not target a method.

    This is logically part of analyse_member_access and the arguments are
    similar.
    """
    # It was not a method. Try looking up a variable.
    v = lookup_member_var_or_accessor(info, name, is_lvalue)

    vv = v
    if isinstance(vv, Decorator):
        # The associated Var node of a decorator contains the type.
        v = vv.var

    if isinstance(v, Var):
        # Found a member variable.
        var = v
        itype = map_instance_to_supertype(itype, var.info)
        if var.type:
            t = expand_type_by_instance(var.type, itype)
            if (var.is_initialized_in_class and isinstance(t, FunctionLike)
                    and not var.is_staticmethod):
                # Class-level function object becomes a bound method.
                functype = cast(FunctionLike, t)
                check_method_type(functype, itype, node, msg)
                signature = method_type(functype)
                if var.is_property:
                    if is_lvalue:
                        msg.read_only_property(name, info, node)
                    # A property cannot have an overloaded type => the cast
                    # is fine.
                    return cast(Callable, signature).ret_type
                else:
                    return signature
            return t
        else:
            if not var.is_ready:
                msg.cannot_determine_type(var.name(), node)
            # Implicit 'Any' type.
            return AnyType()
    elif isinstance(v, FuncDef):
        assert False, "Did not expect a function"

    # Could not find the member.
    if is_super:
        msg.undefined_in_superclass(name, node)
        return AnyType()
    else:
        return msg.has_no_attr(report_type or itype, name, node)
Beispiel #5
0
def analyze_var(
    name: str, var: Var, itype: Instance, info: TypeInfo, node: Context, is_lvalue: bool, msg: MessageBuilder
) -> Type:
    """Analyze access to an attribute via a Var node.

    This is conceptually part of analyze_member_access and the arguments are similar.
    """
    # Found a member variable.
    itype = map_instance_to_supertype(itype, var.info)
    if var.type:
        t = expand_type_by_instance(var.type, itype)
        if var.is_initialized_in_class and isinstance(t, FunctionLike):
            if is_lvalue:
                if var.is_property:
                    if not var.is_settable_property:
                        msg.read_only_property(name, info, node)
                else:
                    msg.cant_assign_to_method(node)

            if not var.is_staticmethod:
                # Class-level function objects and classmethods become bound
                # methods: the former to the instance, the latter to the
                # class.
                functype = cast(FunctionLike, t)
                check_method_type(functype, itype, node, msg)
                signature = method_type(functype)
                if var.is_property:
                    # A property cannot have an overloaded type => the cast
                    # is fine.
                    return cast(CallableType, signature).ret_type
                else:
                    return signature
        return t
    else:
        if not var.is_ready:
            msg.cannot_determine_type(var.name(), node)
        # Implicit 'Any' type.
        return AnyType()
Beispiel #6
0
def analyze_var(name: str, var: Var, itype: Instance, info: TypeInfo,
                node: Context, is_lvalue: bool, msg: MessageBuilder) -> Type:
    """Analyze access to an attribute via a Var node.

    This is conceptually part of analyze_member_access and the arguments are similar.
    """
    # Found a member variable.
    itype = map_instance_to_supertype(itype, var.info)
    if var.type:
        t = expand_type_by_instance(var.type, itype)
        if var.is_initialized_in_class and isinstance(t, FunctionLike):
            if is_lvalue:
                if var.is_property:
                    if not var.is_settable_property:
                        msg.read_only_property(name, info, node)
                else:
                    msg.cant_assign_to_method(node)

            if not var.is_staticmethod:
                # Class-level function objects and classmethods become bound
                # methods: the former to the instance, the latter to the
                # class.
                functype = cast(FunctionLike, t)
                check_method_type(functype, itype, node, msg)
                signature = method_type(functype)
                if var.is_property:
                    # A property cannot have an overloaded type => the cast
                    # is fine.
                    return cast(CallableType, signature).ret_type
                else:
                    return signature
        return t
    else:
        if not var.is_ready:
            msg.cannot_determine_type(var.name(), node)
        # Implicit 'Any' type.
        return AnyType()