コード例 #1
0
ファイル: constraints.py プロジェクト: FlorianLudwig/mypy
 def visit_instance(self, template: Instance) -> List[Constraint]:
     actual = self.actual
     if isinstance(actual, Instance):
         res = [] # type: List[Constraint]
         instance = cast(Instance, actual)
         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 the default constraint and its
                 # negation to achieve the effect.
                 cb = infer_constraints(mapped.args[i], instance.args[i],
                                        self.direction)
                 res.extend(cb)
                 res.extend(negate_constraints(cb))
             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.
                 cb = infer_constraints(template.args[j], mapped.args[j],
                                        self.direction)
                 res.extend(cb)
                 res.extend(negate_constraints(cb))
             return res
     if isinstance(actual, AnyType):
         # IDEA: Include both ways, i.e. add negation as well?
         return self.infer_against_any(template.args)
     else:
         return []
コード例 #2
0
ファイル: constraints.py プロジェクト: silky/mypy
 def visit_instance(self, template: Instance) -> List[Constraint]:
     actual = self.actual
     if isinstance(actual, Instance):
         res = []  # type: List[Constraint]
         instance = cast(Instance, actual)
         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 the default constraint and its
                 # negation to achieve the effect.
                 cb = infer_constraints(mapped.args[i], instance.args[i],
                                        self.direction)
                 res.extend(cb)
                 res.extend(negate_constraints(cb))
             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.
                 cb = infer_constraints(template.args[j], mapped.args[j],
                                        self.direction)
                 res.extend(cb)
                 res.extend(negate_constraints(cb))
             return res
     if isinstance(actual, AnyType):
         # IDEA: Include both ways, i.e. add negation as well?
         return self.infer_against_any(template.args)
     else:
         return []
コード例 #3
0
ファイル: transformtype.py プロジェクト: adamhaney/mypy
 def make_tvar_init_expression(self, info: TypeInfo, slot: int) -> TypeExpr:
     """Return the initializer for the given slot in the given type.
     
     This is the type expression that initializes the given slot
     using the type arguments given to the constructor.
     
     Examples:
       - In 'class C(Generic[T]) ...', the initializer for the slot 0 is
         TypeExpr(RuntimeTypeVar(NameExpr('__tv'))).
       - In 'class D(C[int]) ...', the initializer for the slot 0 is
         TypeExpr(<int instance>).
     """
     # Figure out the superclass which defines the slot; also figure out
     # the tvar index that maps to the slot.
     origin, tv = find_slot_origin(info, slot)
     
     # Map self type to the superclass -> extract tvar with target index
     # (only contains subclass tvars?? PROBABLY NOT).
     selftype = self_type(info)
     selftype = map_instance_to_supertype(selftype, origin)
     tvar = selftype.args[tv - 1]
     
     # Map tvar to an expression; refer to local vars instead of member
     # vars always.
     tvar = translate_runtime_type_vars_locally(tvar)
     
     # Build the rvalue (initializer) expression
     return TypeExpr(tvar)
コード例 #4
0
ファイル: transformtype.py プロジェクト: adamhaney/mypy
    def make_superclass_constructor_call(
            self, info: TypeInfo, callee_type: Callable) -> ExpressionStmt:
        """Construct a statement that calls the superclass constructor.

        In particular, it passes any type variables arguments as needed.
        """
        callee = SuperExpr('__init__')
        callee.info = info
        
        # We do not handle generic constructors. Either pass runtime
        # type variables from the current scope or perhaps require
        # explicit constructor in this case.
        
        selftype = self_type(info)    
        
        # FIX overloading
        # FIX default args / varargs
        
        # Map self type to the superclass context.
        base = info.mro[1]
        selftype = map_instance_to_supertype(selftype, base)
        
        super_init = cast(FuncDef, base.get_method('__init__'))
        
        # Add constructor arguments.
        args = [] # type: List[Node]
        for n in range(1, callee_type.min_args):            
            args.append(NameExpr(super_init.args[n].name()))
            self.tf.set_type(args[-1], callee_type.arg_types[n])

        # Store callee type after stripping away the 'self' type.
        self.tf.set_type(callee, nodes.method_callable(callee_type))
        
        call = CallExpr(callee, args, [nodes.ARG_POS] * len(args))
        return ExpressionStmt(call)
コード例 #5
0
def compile_slot_mapping(typ: TypeInfo) -> List[Type]:
    """Return types that represent values of type variable slots of a type.

    The returned types are in terms of type variables of the type.

    For example, assume these definitions:

      class D(Generic[S]): ...
      class C(D[E[S]], Generic[T, S]): ...

    Now slot mappings for C is [E[S], T] (S and T refer to type variables of
    C).
    """
    exprs = []  # type: List[Type]

    for slot in range(num_slots(typ)):
        # Figure out the superclass which defines the slot; also figure out
        # the tvar index that maps to the slot.
        origin, tv = find_slot_origin(typ, slot)

        # Map self type to the superclass -> extract tvar with target index
        # (only contains subclass tvars?? PROBABLY NOT).
        selftype = self_type(typ)
        selftype = map_instance_to_supertype(selftype, origin)
        tvar = selftype.args[tv - 1]

        # tvar is the representation of the slot in terms of type arguments.
        exprs.append(tvar)

    return exprs
コード例 #6
0
ファイル: transformtype.py プロジェクト: SRiikonen/mypy-py
    def make_superclass_constructor_call(self, info, callee_type):
        """Construct a statement that calls the superclass constructor.

        In particular, it passes any type variables arguments as needed.
        """
        callee = SuperExpr('__init__')
        callee.info = info
        
        # We do not handle generic constructors. Either pass runtime
        # type variables from the current scope or perhaps require
        # explicit constructor in this case.
        
        selftype = self_type(info)    
        
        # FIX overloading
        # FIX default args / varargs
        
        # Map self type to the superclass context.
        selftype = map_instance_to_supertype(selftype, info.base)
        
        super_init = info.base.get_method('__init__')
        
        # Add constructor arguments.
        args = []
        for n in range(1, callee_type.min_args):            
            args.append(NameExpr(super_init.args[n].name()))
            self.tf.set_type(args[-1], callee_type.arg_types[n])

        # Store callee type after stripping away the 'self' type.
        self.tf.set_type(callee, nodes.method_callable(callee_type))
        
        call = CallExpr(callee, args, [nodes.ARG_POS] * len(args))
        return ExpressionStmt(call)
コード例 #7
0
ファイル: transformtype.py プロジェクト: SRiikonen/mypy-py
 def make_tvar_init_expression(self, info, slot):
     """Return the initializer for the given slot in the given type.
     
     This is the type expression that initializes the given slot
     using the type arguments given to the constructor.
     
     Examples:
       - In 'class C<T> ...', the initializer for the slot 0 is
         TypeExpr(RuntimeTypeVar(NameExpr('__tv'))).
       - In 'class D(C<int>) ...', the initializer for the slot 0 is
         TypeExpr(<int instance>).
     """
     # Figure out the superclass which defines the slot; also figure out
     # the tvar index that maps to the slot.
     origin, tv = find_slot_origin(info, slot)
     
     # Map self type to the superclass -> extract tvar with target index
     # (only contains subclass tvars?? PROBABLY NOT).
     selftype = self_type(info)
     selftype = map_instance_to_supertype(selftype, origin)
     tvar = selftype.args[tv - 1]
     
     # Map tvar to an expression; refer to local vars instead of member
     # vars always.
     tvar = translate_runtime_type_vars_locally(tvar)
     
     # Build the rvalue (initializer) expression
     return TypeExpr(tvar)
コード例 #8
0
ファイル: checker.py プロジェクト: SRiikonen/mypy-py
def map_type_from_supertype(typ, sub_info, super_info):
    """Map type variables in a type defined in a supertype context to be valid
    in the subtype context. Assume that the result is unique; if more than
    one type is possible, return one of the alternatives.
    
    For example, assume
    
      class D<S> ...
      class C<T> is D<E<T>> ...
    
    Now S in the context of D would be mapped to E<T> in the context of C.
    """
    # Create the type of self in subtype, of form t<a1, ...>.
    inst_type = self_type(sub_info)
    # Map the type of self to supertype. This gets us a description of the
    # supertype type variables in terms of subtype variables, i.e. t<t1, ...>
    # so that any type variables in tN are to be interpreted in subtype
    # context.
    inst_type = map_instance_to_supertype(inst_type, super_info)
    # Finally expand the type variables in type with those in the previously
    # constructed type. Note that both type and inst_type may have type
    # variables, but in type they are interpreterd in supertype context while
    # in inst_type they are interpreted in subtype context. This works even if
    # the names of type variables in supertype and subtype overlap.
    return expand_type_by_instance(typ, inst_type)
コード例 #9
0
ファイル: join.py プロジェクト: SRiikonen/mypy-py
def implemented_interfaces(t):
    """If t is a class instance, return all the directly implemented interface
    types by t and its supertypes, including mapped type arguments.
    """
    if t.type.is_interface:
        return [t]
    else:
        res = []
        
        for iface in t.type.interfaces:
            res.append(map_instance_to_supertype(t, iface))
        
        if t.type.base is not None:
            tt = map_instance_to_supertype(t, t.type.base)
            res.extend(implemented_interfaces(tt))
        
        return res
コード例 #10
0
ファイル: checkmember.py プロジェクト: mvcisback/mypy
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)
コード例 #11
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)
コード例 #12
0
ファイル: join.py プロジェクト: silky/mypy
def join_instances_via_supertype(t: Instance, s: Instance,
                                 allow_interfaces: bool,
                                 basic: BasicTypes) -> Type:
    res = s
    mapped = map_instance_to_supertype(t, t.type.bases[0].type)
    join = join_instances(mapped, res, False, basic)
    # If the join failed, fail. This is a defensive measure (this might
    # never happen).
    if isinstance(join, ErrorType):
        return join
    # Now the result must be an Instance, so the cast below cannot fail.
    res = cast(Instance, join)
    return res
コード例 #13
0
ファイル: join.py プロジェクト: bogdan-kulynych/mypy
def join_instances_via_supertype(t: Instance, s: Instance,
                                 allow_interfaces: bool,
                                 basic: BasicTypes) -> Type:
    res = s
    mapped = map_instance_to_supertype(t, t.type.bases[0].type)
    join = join_instances(mapped, res, False, basic)
    # If the join failed, fail. This is a defensive measure (this might
    # never happen).
    if isinstance(join, ErrorType):
        return join
    # Now the result must be an Instance, so the cast below cannot fail.
    res = cast(Instance, join)
    return res
コード例 #14
0
ファイル: checkmember.py プロジェクト: SRiikonen/mypy-py
def analyse_member_access(name, typ, node, is_lvalue, is_super, tuple_type, msg, override_info=None):
    """Analyse member access.

    This is a general operation that supports various different variations:
    
      1. lvalue or non-lvalue access (i.e. setter or getter access)
      2. supertype access (when using super(); is_super == True and
         override_info should refer to the supertype)
    """
    if isinstance(typ, Instance):
        if name == "__init__" and not is_super:
            # Accessing __init__ in statically typed code would compromise
            # type safety unless used via super().
            msg.fail(messages.CANNOT_ACCESS_INIT, node)
            return Any()

        # The base object has an instance type.
        itype = typ

        info = itype.type
        if override_info:
            info = override_info

        # Look up the member. First look up the method dictionary.
        method = None
        if not is_lvalue:
            method = info.get_method(name)

        if method:
            # Found a method. The call below has a unique result for all valid
            # programs.
            itype = map_instance_to_supertype(itype, method.info)
            return expand_type_by_instance(method_type(method), itype)
        else:
            # Not a method.
            return analyse_member_var_access(name, itype, info, node, is_lvalue, is_super, msg)
    elif isinstance(typ, Any):
        # The base object has dynamic type.
        return Any()
    elif isinstance(typ, TupleType):
        # Actually look up from the tuple type.
        return analyse_member_access(name, tuple_type, node, is_lvalue, is_super, tuple_type, msg)
    elif isinstance(typ, Callable) and (typ).is_type_obj():
        # Class attribute access.
        return msg.not_implemented("class attributes", node)
    else:
        # The base object has an unsupported type.
        return msg.has_no_member(typ, name, node)
コード例 #15
0
ファイル: join.py プロジェクト: SRiikonen/mypy-py
def join_instances_via_supertype(t, s, allow_interfaces, basic):
    res = s
    mapped = map_instance_to_supertype(t, t.type.base)
    join = join_instances(mapped, res, False, basic)
    # If the join failed, fail. This is a defensive measure (this might
    # never happen).
    if isinstance(join, ErrorType):
        return join
    # Now the result must be an Instance, so the cast below cannot fail.
    res = join
    
    if (res.type == basic.object.type and not t.type.is_interface and
            allow_interfaces):
        return join_instances_as_interface(t, s, basic)
    else:
        return res
コード例 #16
0
ファイル: join.py プロジェクト: FlorianLudwig/mypy
def join_instances_via_supertype(t: Instance, s: Instance,
                                 basic: BasicTypes) -> Type:
    # Give preference to joins via duck typing relationship, so that
    # join(int, float) == float, for example.
    if t.type.ducktype and is_subtype(t.type.ducktype, s):
        return join_types(t.type.ducktype, s, basic)
    elif s.type.ducktype and is_subtype(s.type.ducktype, t):
        return join_types(t, s.type.ducktype, basic)
    res = s
    mapped = map_instance_to_supertype(t, t.type.bases[0].type)
    join = join_instances(mapped, res, basic)
    # If the join failed, fail. This is a defensive measure (this might
    # never happen).
    if isinstance(join, ErrorType):
        return join
    # Now the result must be an Instance, so the cast below cannot fail.
    res = cast(Instance, join)
    return res
コード例 #17
0
def join_instances_via_supertype(t: Instance, s: Instance,
                                 basic: BasicTypes) -> Type:
    # Give preference to joins via duck typing relationship, so that
    # join(int, float) == float, for example.
    if t.type.ducktype and is_subtype(t.type.ducktype, s):
        return join_types(t.type.ducktype, s, basic)
    elif s.type.ducktype and is_subtype(s.type.ducktype, t):
        return join_types(t, s.type.ducktype, basic)
    res = s
    mapped = map_instance_to_supertype(t, t.type.bases[0].type)
    join = join_instances(mapped, res, basic)
    # If the join failed, fail. This is a defensive measure (this might
    # never happen).
    if isinstance(join, ErrorType):
        return join
    # Now the result must be an Instance, so the cast below cannot fail.
    res = cast(Instance, join)
    return res
コード例 #18
0
ファイル: checkmember.py プロジェクト: SRiikonen/mypy-py
def analyse_member_var_access(name, itype, info, node, is_lvalue, is_super, msg):
    """Analyse member 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)

    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):
                # Class-level function object becomes a bound method.
                functype = t
                check_method_type(functype, itype, node, msg)
                return method_type(functype)
            return t
        else:
            if not var.is_ready:
                msg.cannot_determine_type(var.name(), node)
            # Implicit 'any' type.
            return Any()
    elif isinstance(v, FuncDef):
        # Found a getter or a setter.
        raise NotImplementedError()

    # Could not find the member.
    if is_super:
        msg.undefined_in_superclass(name, node)
        return Any()
    else:
        return msg.has_no_member(itype, name, node)
コード例 #19
0
ファイル: constraints.py プロジェクト: SRiikonen/mypy
 
 # Non-trivial leaf type
 
 Constraint[] visit_type_var(self, TypeVar template):
     return [Constraint(template.id, SUPERTYPE_OF, self.actual)]
 
 # Non-leaf types
 
 Constraint[] visit_instance(self, Instance template):
     actual = self.actual
     if isinstance(actual, Instance):
         res = <Constraint> []
         instance = (Instance)actual
         if (self.direction == SUBTYPE_OF and
                 template.type.has_base(instance.type.full_name())):
             mapped = map_instance_to_supertype(template, instance.type)
             for i in range(len(instance.args)):
                 # The constraints for generic type parameters are
                 # invariant. Include the default constraint and its
                 # negation to achieve the effect.
                 cb = infer_constraints(mapped.args[i], instance.args[i],
                                        self.direction)
                 res.extend(cb)
                 res.extend(negate_constraints(cb))
             return res
         elif (self.direction == SUPERTYPE_OF and
                 instance.type.has_base(template.type.full_name())):
             mapped = map_instance_to_supertype(instance, template.type)
             for j in range(len(template.args)):
                 # The constraints for generic type parameters are
                 # invariant.
コード例 #20
0
ファイル: transformtype.py プロジェクト: SRiikonen/mypy-py
    def make_init_wrapper(self, tdef):
        """Make and return an implicit __init__ if class needs it.
        
        Otherwise, return an empty list. We include an implicit
        __init__ if the class is generic or if it extends a generic class
        and if it does not define __init__.
        
        The __init__ of a generic class requires one or more extra type
        variable arguments. The inherited __init__ may not accept these.

        For example, assume these definitions:
        
        . class A<T>: pass
        . class B(A<int>): pass
        
        The constructor for B will be (equivalent to)
        
        . void __init__(B self):
        .     self.__tv = <int>
        .     super().__init__(<int>)
        """
        
        # FIX overloading, default args / varargs, keyword args

        info = tdef.info
        
        if '__init__' not in info.methods and (
                tdef.is_generic() or (info.base and info.base.is_generic())):
            # Generic class with no explicit __init__ method
            # (i.e. __init__ inherited from superclass). Generate a
            # wrapper that initializes type variable slots and calls
            # the superclass __init__ method.
            
            selftype = self_type(info)    
            callee_type = analyse_member_access(
                '__init__', selftype, None, False, True, None, None,
                info.base)
            
            # Now the callee type may contain the type variables of a
            # grandparent as bound type variables, but we want the
            # type variables of the parent class. Explicitly set the
            # bound type variables.
            callee_type = self.fix_bound_init_tvars(callee_type,
                map_instance_to_supertype(selftype, info.base))
            
            super_init = info.base.get_method('__init__')
            
            # Build argument list.
            args = [Var('self')]
            for i in range(1, len(super_init.args)):
                args.append(Var(super_init.args[i].name()))
                args[-1].type = callee_type.arg_types[i - 1]

            selft = self_type(self.tf.type_context())
            callee_type = prepend_arg_type(callee_type, selft)
            
            creat = FuncDef('__init__', args,
                            super_init.arg_kinds, [None] * len(args),
                            Block([]))
            creat.info = tdef.info
            creat.type = callee_type
            creat.is_implicit = False
            tdef.info.methods['__init__'] = creat
            
            # Insert a call to superclass constructor. If the
            # superclass is object, the constructor does nothing =>
            # omit the call.
            if tdef.info.base.full_name() != 'builtins.object':
                creat.body.body.append(
                    self.make_superclass_constructor_call(tdef.info,
                                                          callee_type))
            
            # Implicit cast from FuncDef[] to Node[] is safe below.
            return self.func_tf.transform_method(creat)
        else:
            return []
コード例 #21
0
ファイル: transformtype.py プロジェクト: SRiikonen/mypy
            # Generic class with no explicit __init__ method
            # (i.e. __init__ inherited from superclass). Generate a
            # wrapper that initializes type variable slots and calls
            # the superclass __init__ method.
            
            selftype = self_type(info)    
            callee_type = (Callable)analyse_member_access(
                '__init__', selftype, None, False, True, None, None,
                info.base)
            
            # Now the callee type may contain the type variables of a
            # grandparent as bound type variables, but we want the
            # type variables of the parent class. Explicitly set the
            # bound type variables.
            callee_type = self.fix_bound_init_tvars(callee_type,
                map_instance_to_supertype(selftype, info.base))
            
            super_init = (FuncDef)info.base.get_method('__init__')
            
            # Build argument list.
            args = [Var('self')]
            for i in range(1, len(super_init.args)):
                args.append(Var(super_init.args[i].name()))
                args[-1].type = callee_type.arg_types[i - 1]

            selft = self_type(self.tf.type_context())
            callee_type = prepend_arg_type(callee_type, selft)
            
            creat = FuncDef('__init__', args,
                            super_init.arg_kinds,
                            <Node> [None] * len(args),
コード例 #22
0
ファイル: checkmember.py プロジェクト: prodigeni/mypy
def analyse_member_access(name: str,
                          typ: Type,
                          node: Context,
                          is_lvalue: bool,
                          is_super: bool,
                          basic_types: BasicTypes,
                          msg: MessageBuilder,
                          override_info: TypeInfo = None,
                          report_type: Type = None) -> Type:
    """Analyse attribute access.

    This is a general operation that supports various different variations:

      1. lvalue or non-lvalue access (i.e. setter or getter access)
      2. supertype access (when using super(); is_super == True and
         override_info should refer to the supertype)
    """
    report_type = report_type or typ
    if isinstance(typ, Instance):
        if name == '__init__' and not is_super:
            # Accessing __init__ in statically typed code would compromise
            # type safety unless used via super().
            msg.fail(messages.CANNOT_ACCESS_INIT, node)
            return AnyType()

        # The base object has an instance type.

        info = typ.type
        if override_info:
            info = override_info

        # Look up the member. First look up the method dictionary.
        method = info.get_method(name)
        if method:
            if is_lvalue:
                msg.cant_assign_to_method(node)
            typ = map_instance_to_supertype(typ, method.info)
            return expand_type_by_instance(method_type(method), typ)
        else:
            # Not a method.
            return analyse_member_var_access(name,
                                             typ,
                                             info,
                                             node,
                                             is_lvalue,
                                             is_super,
                                             msg,
                                             report_type=report_type)
    elif isinstance(typ, AnyType):
        # The base object has dynamic type.
        return AnyType()
    elif isinstance(typ, UnionType):
        # The base object has dynamic type.
        msg.disable_type_names += 1
        results = [
            analyse_member_access(name, subtype, node, is_lvalue, is_super,
                                  basic_types, msg) for subtype in typ.items
        ]
        msg.disable_type_names -= 1
        return UnionType.make_simplified_union(results)
    elif isinstance(typ, TupleType):
        # Actually look up from the 'tuple' type.
        return analyse_member_access(name, basic_types.tuple, node, is_lvalue,
                                     is_super, basic_types, msg)
    elif (isinstance(typ, FunctionLike)
          and cast(FunctionLike, typ).is_type_obj()):
        # Class attribute.
        # TODO super?
        sig = cast(FunctionLike, typ)
        itype = cast(Instance, sig.items()[0].ret_type)
        result = analyse_class_attribute_access(itype, name, node, is_lvalue,
                                                msg)
        if result:
            return result
        # Look up from the 'type' type.
        return analyse_member_access(name,
                                     basic_types.type_type,
                                     node,
                                     is_lvalue,
                                     is_super,
                                     basic_types,
                                     msg,
                                     report_type=report_type)
    elif isinstance(typ, FunctionLike):
        # Look up from the 'function' type.
        return analyse_member_access(name,
                                     basic_types.function,
                                     node,
                                     is_lvalue,
                                     is_super,
                                     basic_types,
                                     msg,
                                     report_type=report_type)
    return msg.has_no_attr(report_type, name, node)
コード例 #23
0
ファイル: transformtype.py プロジェクト: adamhaney/mypy
    def make_init_wrapper(self, tdef: ClassDef) -> List[Node]:
        """Make and return an implicit __init__ if class needs it.
        
        Otherwise, return an empty list. We include an implicit
        __init__ if the class is generic or if it extends a generic class
        and if it does not define __init__.
        
        The __init__ of a generic class requires one or more extra type
        variable arguments. The inherited __init__ may not accept these.

        For example, assume these definitions:
        
        . class A(Generic[T]): pass
        . class B(A[int]): pass
        
        The constructor for B will be (equivalent to)
        
        . def __init__(self: B) -> None:
        .     self.__tv = <int>
        .     super().__init__(<int>)
        """
        
        # FIX overloading, default args / varargs, keyword args

        info = tdef.info
        
        if '__init__' not in info.names and (
                tdef.is_generic() or (info.bases and
                                      info.mro[1].is_generic())):
            # Generic class with no explicit __init__ method
            # (i.e. __init__ inherited from superclass). Generate a
            # wrapper that initializes type variable slots and calls
            # the superclass __init__ method.

            base = info.mro[1]
            selftype = self_type(info)    
            callee_type = cast(Callable, analyse_member_access(
                '__init__', selftype, None, False, True, None, None,
                base))
            
            # Now the callee type may contain the type variables of a
            # grandparent as bound type variables, but we want the
            # type variables of the parent class. Explicitly set the
            # bound type variables.
            callee_type = self.fix_bound_init_tvars(callee_type,
                map_instance_to_supertype(selftype, base))
            
            super_init = cast(FuncDef, base.get_method('__init__'))
            
            # Build argument list.
            args = [Var('self')]
            for i in range(1, len(super_init.args)):
                args.append(Var(super_init.args[i].name()))
                args[-1].type = callee_type.arg_types[i - 1]

            selft = self_type(self.tf.type_context())
            callee_type = prepend_arg_type(callee_type, selft)
            
            creat = FuncDef('__init__', args,
                            super_init.arg_kinds, [None] * len(args),
                            Block([]))
            creat.info = tdef.info
            creat.type = callee_type
            creat.is_implicit = False
            tdef.info.names['__init__'] = SymbolTableNode(MDEF, creat,
                                                          typ=creat.type)
            
            # Insert a call to superclass constructor. If the
            # superclass is object, the constructor does nothing =>
            # omit the call.
            if base.fullname() != 'builtins.object':
                creat.body.body.append(
                    self.make_superclass_constructor_call(tdef.info,
                                                          callee_type))
            
            # Implicit cast from FuncDef[] to Node[] is safe below.
            return Any(self.func_tf.transform_method(creat))
        else:
            return []
コード例 #24
0
ファイル: checkmember.py プロジェクト: mvcisback/mypy
def analyse_member_access(name: str, typ: Type, node: Context, is_lvalue: bool,
                          is_super: bool, basic_types: BasicTypes,
                          msg: MessageBuilder, override_info: TypeInfo = None,
                          report_type: Type = None) -> Type:
    """Analyse attribute access.

    This is a general operation that supports various different variations:
    
      1. lvalue or non-lvalue access (i.e. setter or getter access)
      2. supertype access (when using super(); is_super == True and
         override_info should refer to the supertype)
    """
    report_type = report_type or typ
    if isinstance(typ, Instance):
        if name == '__init__' and not is_super:
            # Accessing __init__ in statically typed code would compromise
            # type safety unless used via super().
            msg.fail(messages.CANNOT_ACCESS_INIT, node)
            return AnyType()
        
        # The base object has an instance type.
        
        info = typ.type
        if override_info:
            info = override_info
        
        # Look up the member. First look up the method dictionary.
        method = info.get_method(name)
        if method:
            if is_lvalue:
                msg.cant_assign_to_method(node)
            typ = map_instance_to_supertype(typ, method.info)
            return expand_type_by_instance(method_type(method), typ)
        else:
            # Not a method.
            return analyse_member_var_access(name, typ, info, node,
                                             is_lvalue, is_super, msg,
                                             report_type=report_type)
    elif isinstance(typ, AnyType):
        # The base object has dynamic type.
        return AnyType()
    elif isinstance(typ, UnionType):
        # The base object has dynamic type.
        msg.disable_type_names += 1
        results = [analyse_member_access(name, subtype, node, is_lvalue,
                                         is_super, basic_types, msg)
                   for subtype in typ.items]
        msg.disable_type_names -= 1
        return UnionType.make_simplified_union(results)
    elif isinstance(typ, TupleType):
        # Actually look up from the 'tuple' type.
        return analyse_member_access(name, basic_types.tuple, node, is_lvalue,
                                     is_super, basic_types, msg)
    elif (isinstance(typ, FunctionLike) and
              cast(FunctionLike, typ).is_type_obj()):
        # Class attribute.
        # TODO super?
        sig = cast(FunctionLike, typ)
        itype = cast(Instance, sig.items()[0].ret_type)
        result = analyse_class_attribute_access(itype, name, node, is_lvalue,
                                                msg)
        if result:
            return result
        # Look up from the 'type' type.
        return analyse_member_access(name, basic_types.type_type, node,
                                     is_lvalue, is_super, basic_types, msg,
                                     report_type=report_type)
    elif isinstance(typ, FunctionLike):
        # Look up from the 'function' type.
        return analyse_member_access(name, basic_types.function, node,
                                     is_lvalue, is_super, basic_types, msg,
                                     report_type=report_type)
    return msg.has_no_attr(report_type, name, node)
コード例 #25
0
ファイル: compileslotmap.py プロジェクト: SRiikonen/mypy
    . class D<S>(object): ...
    
    Now slot mappings for C is [E<S>, T] (S and T refer to type variables of
    C).
    """
    Type[] exprs = []
    
    for slot in range(num_slots(typ)):
        # Figure out the superclass which defines the slot; also figure out
        # the tvar index that maps to the slot.
        origin, tv = find_slot_origin(typ, slot)
        
        # Map self type to the superclass -> extract tvar with target index
        # (only contains subclass tvars?? PROBABLY NOT).
        selftype = self_type(typ)
        selftype = map_instance_to_supertype(selftype, origin)
        tvar = selftype.args[tv - 1]
        
        # tvar is the representation of the slot in terms of type arguments.
        exprs.append(tvar)
    
    return exprs


tuple<TypeInfo, int> find_slot_origin(TypeInfo info, int slot):
    """Determine class and type variable index that directly maps to the slot.

    The result defines which class in inheritance hierarchy of info introduced
    the slot. All subclasses inherit this slot. The result TypeInfo always
    refers to one of the base classes of info (or info itself).
コード例 #26
0
ファイル: checkmember.py プロジェクト: SRiikonen/mypy
     # The base object has an instance type.
     itype = (Instance)typ
     
     info = itype.type
     if override_info:
         info = override_info
     
     # Look up the member. First look up the method dictionary.
     FuncBase method = None
     if not is_lvalue:
         method = info.get_method(name)
     
     if method:
         # Found a method. The call below has a unique result for all valid
         # programs.
         itype = map_instance_to_supertype(itype, method.info)
         return expand_type_by_instance(method_type(method), itype)
     else:
         # Not a method.
         return analyse_member_var_access(name, itype, info, node,
                                          is_lvalue, is_super, msg)
 elif isinstance(typ, Any):
     # The base object has dynamic type.
     return Any()
 elif isinstance(typ, TupleType):
     # Actually look up from the tuple type.
     return analyse_member_access(name, tuple_type, node, is_lvalue,
                                  is_super, tuple_type, msg)
 elif isinstance(typ, Callable) and ((Callable)typ).is_type_obj():
     # Class attribute access.
     return msg.not_implemented('class attributes', node)