Example #1
0
    def visit_Attribute(self, n: ast3.Attribute) -> Type:
        before_dot = self.visit(n.value)

        if isinstance(before_dot, UnboundType) and not before_dot.args:
            return UnboundType("{}.{}".format(before_dot.name, n.attr), line=self.line)
        else:
            self.fail(TYPE_COMMENT_AST_ERROR, self.line, getattr(n, 'col_offset', -1))
            return AnyType()
Example #2
0
    def test_error_type(self):
        self.assert_join(self.fx.err, self.fx.anyt, self.fx.anyt)

        # Meet against any type except dynamic results in ErrorType.
        for t in [self.fx.a, self.fx.o, NoneTyp(), UnboundType('x'),
                  self.fx.void, self.fx.t, self.tuple(),
                  self.callable(self.fx.a, self.fx.b)]:
            self.assert_join(t, self.fx.err, self.fx.err)
Example #3
0
def expr_to_unanalyzed_type(expr: Expression) -> Type:
    """Translate an expression to the corresponding type.

    The result is not semantically analyzed. It can be UnboundType or TypeList.
    Raise TypeTranslationError if the expression cannot represent a type.
    """
    if isinstance(expr, NameExpr):
        name = expr.name
        return UnboundType(name, line=expr.line, column=expr.column)
    elif isinstance(expr, MemberExpr):
        fullname = get_member_expr_fullname(expr)
        if fullname:
            return UnboundType(fullname, line=expr.line, column=expr.column)
        else:
            raise TypeTranslationError()
    elif isinstance(expr, IndexExpr):
        base = expr_to_unanalyzed_type(expr.base)
        if isinstance(base, UnboundType):
            if base.args:
                raise TypeTranslationError()
            if isinstance(expr.index, TupleExpr):
                args = expr.index.items
            else:
                args = [expr.index]
            base.args = [expr_to_unanalyzed_type(arg) for arg in args]
            if not base.args:
                base.empty_tuple_index = True
            return base
        else:
            raise TypeTranslationError()
    elif isinstance(expr, ListExpr):
        return TypeList([expr_to_unanalyzed_type(t) for t in expr.items],
                        line=expr.line,
                        column=expr.column)
    elif isinstance(expr, (StrExpr, BytesExpr, UnicodeExpr)):
        # Parse string literal type.
        try:
            result = parse_type_comment(expr.value, expr.line, None)
        except SyntaxError:
            raise TypeTranslationError()
        return result
    elif isinstance(expr, EllipsisExpr):
        return EllipsisType(expr.line)
    else:
        raise TypeTranslationError()
Example #4
0
    def test_none(self) -> None:
        self.assert_meet(NoneType(), NoneType(), NoneType())

        self.assert_meet(NoneType(), self.fx.anyt, NoneType())

        # Any type t joined with None results in None, unless t is Any.
        for t in [self.fx.a, self.fx.o, UnboundType('x'), self.fx.t,
                  self.tuple(), self.callable(self.fx.a, self.fx.b)]:
            self.assert_meet(t, NoneType(), NoneType())
Example #5
0
 def test_none(self) -> None:
     # Any type t joined with None results in t.
     for t in [
             NoneType(), self.fx.a, self.fx.o,
             UnboundType('x'), self.fx.t,
             self.tuple(),
             self.callable(self.fx.a, self.fx.b), self.fx.anyt
     ]:
         self.assert_join(t, NoneType(), t)
Example #6
0
 def test_any_type(self) -> None:
     # Join against 'Any' type always results in 'Any'.
     for t in [
             self.fx.anyt, self.fx.a, self.fx.o,
             NoneType(),
             UnboundType('x'), self.fx.t,
             self.tuple(),
             self.callable(self.fx.a, self.fx.b)
     ]:
         self.assert_join(t, self.fx.anyt, self.fx.anyt)
Example #7
0
 def test_dynamic_type(self) -> None:
     # Meet against dynamic type always results in dynamic.
     for t in [
             self.fx.anyt, self.fx.a, self.fx.o,
             NoneType(),
             UnboundType('x'), self.fx.t,
             self.tuple(),
             self.callable(self.fx.a, self.fx.b)
     ]:
         self.assert_meet(t, self.fx.anyt, t)
Example #8
0
    def test_void(self):
        self.assert_meet(self.fx.void, self.fx.void, self.fx.void)
        self.assert_meet(self.fx.void, self.fx.anyt, self.fx.void)

        # Meet of any other type against void results in ErrorType, since there
        # is no meaningful valid result.
        for t in [self.fx.a, self.fx.o, UnboundType('x'), NoneTyp(),
                  self.fx.t, self.tuple(),
                  self.callable(self.fx.a, self.fx.b)]:
            self.assert_meet(t, self.fx.void, self.fx.err)
Example #9
0
    def test_void(self):
        self.assert_join(self.fx.void, self.fx.void, self.fx.void)
        self.assert_join(self.fx.void, self.fx.anyt, self.fx.anyt)

        # Join of any other type against void results in ErrorType, since there
        # is no other meaningful result.
        for t in [self.fx.a, self.fx.o, NoneTyp(), UnboundType('x'),
                  self.fx.t, self.tuple(),
                  self.callable(self.fx.a, self.fx.b)]:
            self.assert_join(t, self.fx.void, self.fx.err)
Example #10
0
 def anal_type(self, tp: UnboundType) -> Type:
     tpan = TypeAnalyser(self.api,
                         None,
                         self.plugin,
                         self.options,
                         self.is_typeshed_stub,
                         third_pass=True)
     res = tp.accept(tpan)
     self.aliases_used = tpan.aliases_used
     return res
Example #11
0
 def anal_type(self, tp: UnboundType) -> Type:
     tpan = TypeAnalyser(self.api,
                         None,
                         self.plugin,
                         self.options,
                         self.is_typeshed_stub,
                         third_pass=True)
     res = tp.accept(tpan)
     self.aliases_used = tpan.aliases_used
     return res
Example #12
0
 def anal_type(self, tp: UnboundType) -> Type:
     tpan = TypeAnalyser(self.lookup_func,
                         self.lookup_fqn_func,
                         None,
                         self.fail,
                         self.note_func,
                         self.plugin,
                         self.options,
                         self.is_typeshed_stub,
                         third_pass=True)
     return tp.accept(tpan)
Example #13
0
    def test_unbound_type(self):
        self.assert_meet(UnboundType('x'), UnboundType('x'), self.fx.anyt)
        self.assert_meet(UnboundType('x'), UnboundType('y'), self.fx.anyt)

        self.assert_meet(UnboundType('x'), self.fx.void, self.fx.err)
        self.assert_meet(UnboundType('x'), self.fx.anyt, UnboundType('x'))

        # The meet of any type t with an unbound type results in dynamic
        # (except for void). Unbound type means that there is an error
        # somewhere in the program, so this does not affect type safety.
        for t in [self.fx.a, self.fx.o, self.fx.t, self.tuple(),
                  self.callable(self.fx.a, self.fx.b)]:
            self.assert_meet(t, UnboundType('X'), self.fx.anyt)
Example #14
0
 def test_none(self):
     self.assert_meet(NoneTyp(), NoneTyp(), NoneTyp())
     
     self.assert_meet(NoneTyp(), self.fx.anyt, self.fx.anyt)
     self.assert_meet(NoneTyp(), self.fx.void, self.fx.err)
     
     # Any type t joined with None results in None, unless t is any or
     # void.
     for t in [self.fx.a, self.fx.o, UnboundType('x'), self.fx.t,
               self.tuple(), self.callable(self.fx.a, self.fx.b)]:
         self.assert_meet(t, NoneTyp(), NoneTyp())
Example #15
0
 def anal_type(self, tp: UnboundType) -> Type:
     tpan = TypeAnalyser(self.lookup_func,
                         self.lookup_fqn_func,
                         None,
                         self.fail,
                         self.note_func,
                         self.plugin,
                         self.options,
                         self.is_typeshed_stub,
                         third_pass=True)
     return tp.accept(tpan)
Example #16
0
 def generic_class_wrapper(self, tdef: ClassDef) -> ClassDef:
     """Construct a wrapper class for a generic type."""
     # FIX semanal meta-info for nodes + TypeInfo
     
     defs = [] # type: List[Node]
     
     # Does the type have a superclass, other than builtins.object?
     base = tdef.info.mro[1]
     has_proper_superclass = base.fullname() != 'builtins.object'
     
     if not has_proper_superclass or self.tf.is_java:
         # Generate member variables for wrapper object.
         defs.extend(self.make_generic_wrapper_member_vars(tdef))
     
     for alt in [False, BOUND_VAR]:
         defs.extend(self.make_tvar_representation(tdef.info, alt))
     
     # Generate constructor.
     defs.append(self.make_generic_wrapper_init(tdef.info))
     
     # Generate method wrappers.
     for d in tdef.defs.body:
         if isinstance(d, FuncDef):
             if not d.is_constructor():
                 defs.extend(self.func_tf.generic_method_wrappers(d))
         elif isinstance(d, AssignmentStmt):
             defs.extend(self.generic_accessor_wrappers(d))
         elif not isinstance(d, PassStmt):
             raise RuntimeError(
                 'Definition {} at line {} not supported'.format(
                     type(d), d.line))
     
     base_type = self.tf.named_type('builtins.object') # type: Type
     # Inherit superclass wrapper if there is one.
     if has_proper_superclass:
         base = self.find_generic_base_class(tdef.info)
         if base:
             # TODO bind the type somewhere
             base_type = UnboundType(base.defn.name +
                                     self.tf.wrapper_class_suffix())
     
     # Build the type definition.
     wrapper = ClassDef(tdef.name + self.tf.wrapper_class_suffix(),
                       Block(defs),
                       None,
                       [base_type])
     # FIX fullname
     
     self.tf.add_line_mapping(tdef, wrapper)
     
     return wrapper
Example #17
0
    def visit_Subscript(self, n: ast35.Subscript) -> Type:
        assert isinstance(n.slice, ast35.Index)

        value = self.visit(n.value)

        assert isinstance(value, UnboundType)
        assert not value.args

        if isinstance(n.slice.value, ast35.Tuple):
            params = self.visit_list(n.slice.value.elts)
        else:
            params = [self.visit(n.slice.value)]

        return UnboundType(value.name, params, line=self.line)
Example #18
0
    def visit_Subscript(self, n: ast35.Subscript) -> Type:
        assert isinstance(n.slice, ast35.Index)

        value = self.visit(n.value)

        assert isinstance(value, UnboundType)
        assert not value.args

        empty_tuple_index = False
        if isinstance(n.slice.value, ast35.Tuple):
            params = self.translate_expr_list(n.slice.value.elts)
            if len(n.slice.value.elts) == 0:
                empty_tuple_index = True
        else:
            params = [self.visit(n.slice.value)]

        return UnboundType(value.name, params, line=self.line, empty_tuple_index=empty_tuple_index)
Example #19
0
    def visit_Subscript(self, n: ast3.Subscript) -> Type:
        if not isinstance(n.slice, ast3.Index):
            self.fail(TYPE_COMMENT_SYNTAX_ERROR, self.line, getattr(n, 'col_offset', -1))
            return AnyType(TypeOfAny.from_error)

        empty_tuple_index = False
        if isinstance(n.slice.value, ast3.Tuple):
            params = self.translate_expr_list(n.slice.value.elts)
            if len(n.slice.value.elts) == 0:
                empty_tuple_index = True
        else:
            params = [self.visit(n.slice.value)]

        value = self.visit(n.value)
        if isinstance(value, UnboundType) and not value.args:
            return UnboundType(value.name, params, line=self.line,
                               empty_tuple_index=empty_tuple_index)
        else:
            self.fail(TYPE_COMMENT_AST_ERROR, self.line, getattr(n, 'col_offset', -1))
            return AnyType(TypeOfAny.from_error)
Example #20
0
    def visit_Subscript(self, n: ast35.Subscript) -> Type:
        if not isinstance(n.slice, ast35.Index):
            raise TypeCommentParseError(TYPE_COMMENT_SYNTAX_ERROR, self.line,
                                        getattr(n, 'col_offset', -1))

        value = self.visit(n.value)

        assert isinstance(value, UnboundType)
        assert not value.args

        empty_tuple_index = False
        if isinstance(n.slice.value, ast35.Tuple):
            params = self.translate_expr_list(n.slice.value.elts)
            if len(n.slice.value.elts) == 0:
                empty_tuple_index = True
        else:
            params = [self.visit(n.slice.value)]

        return UnboundType(value.name,
                           params,
                           line=self.line,
                           empty_tuple_index=empty_tuple_index)
Example #21
0
 def visit_unbound_type(self, t: UnboundType) -> Type:
     if t.optional:
         t.optional = False
         # We don't need to worry about double-wrapping Optionals or
         # wrapping Anys: Union simplification will take care of that.
         return make_optional_type(self.visit_unbound_type(t))
     sym = self.lookup(t.name, t,
                       suppress_errors=self.third_pass)  # type: ignore
     if sym is not None:
         if sym.node is None:
             # UNBOUND_IMPORTED can happen if an unknown name was imported.
             if sym.kind != UNBOUND_IMPORTED:
                 self.fail(errorcode.INTERNAL_ERROR_NODE_IS_NONE(sym.kind),
                           t)
             return AnyType(TypeOfAny.special_form)
         fullname = sym.node.fullname()
         hook = self.plugin.get_type_analyze_hook(fullname)
         if hook:
             return hook(AnalyzeTypeContext(t, t, self))
         if (fullname in nongen_builtins and t.args and not sym.normalized
                 and not self.allow_unnormalized):
             self.fail(errorcode.NO_SUBSCRIPT_BUILTIN_ALIAS(fullname), t)
         if self.tvar_scope:
             tvar_def = self.tvar_scope.get_binding(sym)
         else:
             tvar_def = None
         if self.warn_bound_tvar and sym.kind == TVAR and tvar_def is not None:
             self.fail(
                 errorcode.
                 CANNOT_USE_BOUND_TYPE_VAR_TO_DEFINE_GENERIC_ALIAS(t.name),
                 t)
             return AnyType(TypeOfAny.from_error)
         elif sym.kind == TVAR and tvar_def is not None:
             if len(t.args) > 0:
                 self.fail(errorcode.TYPE_VAR_USED_WITH_ARG(t.name), t)
             return TypeVarType(tvar_def, t.line)
         elif fullname == 'builtins.None':
             return NoneTyp()
         elif fullname == 'typing.Any' or fullname == 'builtins.Any':
             return AnyType(TypeOfAny.explicit)
         elif fullname == 'typing.Tuple':
             if len(t.args) == 0 and not t.empty_tuple_index:
                 # Bare 'Tuple' is same as 'tuple'
                 if self.options.disallow_any_generics and not self.is_typeshed_stub:
                     self.fail(errorcode.BARE_GENERIC(), t)
                 typ = self.named_type('builtins.tuple',
                                       line=t.line,
                                       column=t.column)
                 typ.from_generic_builtin = True
                 return typ
             if len(t.args) == 2 and isinstance(t.args[1], EllipsisType):
                 # Tuple[T, ...] (uniform, variable-length tuple)
                 instance = self.named_type('builtins.tuple',
                                            [self.anal_type(t.args[0])])
                 instance.line = t.line
                 return instance
             return self.tuple_type(self.anal_array(t.args))
         elif fullname == 'typing.Union':
             items = self.anal_array(t.args)
             return UnionType.make_union(items)
         elif fullname == 'typing.Optional':
             if len(t.args) != 1:
                 self.fail(errorcode.OPTIONAL_MUST_HAVE_ONE_ARGUMENT(), t)
                 return AnyType(TypeOfAny.from_error)
             item = self.anal_type(t.args[0])
             return make_optional_type(item)
         elif fullname == 'typing.Callable':
             return self.analyze_callable_type(t)
         elif fullname == 'typing.Type':
             if len(t.args) == 0:
                 any_type = AnyType(TypeOfAny.from_omitted_generics,
                                    line=t.line,
                                    column=t.column)
                 return TypeType(any_type, line=t.line, column=t.column)
             if len(t.args) != 1:
                 self.fail(errorcode.TYPE_MUST_HAVE_EXACTLY_ONE_TYPE(), t)
             item = self.anal_type(t.args[0])
             return TypeType.make_normalized(item, line=t.line)
         elif fullname == 'typing.ClassVar':
             if self.nesting_level > 0:
                 self.fail(
                     errorcode.INVALID_TYPE_CLASSVAR_NESTED_INSIDE_TYPE(),
                     t)
             if len(t.args) == 0:
                 return AnyType(TypeOfAny.from_omitted_generics,
                                line=t.line,
                                column=t.column)
             if len(t.args) != 1:
                 self.fail(
                     errorcode.CLASS_VAR_MUST_HAVE_AT_MOST_ONE_TYPE_ARG(),
                     t)
                 return AnyType(TypeOfAny.from_error)
             item = self.anal_type(t.args[0])
             if isinstance(item, TypeVarType) or get_type_vars(item):
                 self.fail(errorcode.CLASSVAR_CANNOT_BE_GENERIC(), t)
                 return AnyType(TypeOfAny.from_error)
             return item
         elif fullname in ('mypy_extensions.NoReturn', 'typing.NoReturn'):
             return UninhabitedType(is_noreturn=True)
         elif sym.kind == TYPE_ALIAS:
             override = sym.type_override
             all_vars = sym.alias_tvars
             assert override is not None
             an_args = self.anal_array(t.args)
             if all_vars is not None:
                 exp_len = len(all_vars)
             else:
                 exp_len = 0
             act_len = len(an_args)
             if exp_len > 0 and act_len == 0:
                 # Interpret bare Alias same as normal generic, i.e., Alias[Any, Any, ...]
                 assert all_vars is not None
                 return set_any_tvars(override, all_vars, t.line, t.column)
             if exp_len == 0 and act_len == 0:
                 return override
             if act_len != exp_len:
                 self.fail(
                     errorcode.BAD_NUMBER_ARGUMENT_FOR_TYPEALIAS(
                         exp_len, act_len), t)
                 return set_any_tvars(override,
                                      all_vars or [],
                                      t.line,
                                      t.column,
                                      implicit=False)
             assert all_vars is not None
             return replace_alias_tvars(override, all_vars, an_args, t.line,
                                        t.column)
         elif not isinstance(sym.node, TypeInfo):
             name = sym.fullname
             if name is None:
                 name = sym.node.name()
             if isinstance(sym.node, Var) and isinstance(
                     sym.node.type, AnyType):
                 # Something with an Any type -- make it an alias for Any in a type
                 # context. This is slightly problematic as it allows using the type 'Any'
                 # as a base class -- however, this will fail soon at runtime so the problem
                 # is pretty minor.
                 return AnyType(TypeOfAny.from_unimported_type)
             # Allow unbound type variables when defining an alias
             if not (self.aliasing and sym.kind == TVAR and
                     (not self.tvar_scope
                      or self.tvar_scope.get_binding(sym) is None)):
                 if (not self.third_pass and not self.in_dynamic_func
                         and not (isinstance(sym.node, (FuncDef, Decorator))
                                  or isinstance(sym.node, Var)
                                  and sym.node.is_ready)
                         and not (sym.kind == TVAR and tvar_def is None)):
                     if t.args and not self.global_scope:
                         self.fail(
                             errorcode.UNSUPPORTED_FORWARD_REFERENCE(
                                 t.name), t)
                         return AnyType(TypeOfAny.from_error)
                     return ForwardRef(t)
                 self.fail(errorcode.INVALID_TYPE_X(name), t)
                 if self.third_pass and sym.kind == TVAR:
                     self.note_func(
                         errorcode.FORWARD_REERENCES_TO_TYPE_VAR_PROHIBITED(
                         ), t)
             return t
         info = sym.node  # type: TypeInfo
         if len(t.args) > 0 and info.fullname() == 'builtins.tuple':
             fallback = Instance(info, [AnyType(TypeOfAny.special_form)],
                                 t.line)
             return TupleType(self.anal_array(t.args), fallback, t.line)
         else:
             # Analyze arguments and construct Instance type. The
             # number of type arguments and their values are
             # checked only later, since we do not always know the
             # valid count at this point. Thus we may construct an
             # Instance with an invalid number of type arguments.
             instance = Instance(info, self.anal_array(t.args), t.line,
                                 t.column)
             instance.from_generic_builtin = sym.normalized
             tup = info.tuple_type
             if tup is not None:
                 # The class has a Tuple[...] base class so it will be
                 # represented as a tuple type.
                 if t.args:
                     self.fail(
                         errorcode.GENERIC_TUPLE_TYPES_NOT_SUPPORTED(), t)
                     return AnyType(TypeOfAny.from_error)
                 return tup.copy_modified(items=self.anal_array(tup.items),
                                          fallback=instance)
             td = info.typeddict_type
             if td is not None:
                 # The class has a TypedDict[...] base class so it will be
                 # represented as a typeddict type.
                 if t.args:
                     self.fail(
                         errorcode.GENERIC_TYPEDDICT_TYPES_NOT_SUPPORTED(),
                         t)
                     return AnyType(TypeOfAny.from_error)
                 # Create a named TypedDictType
                 return td.copy_modified(item_types=self.anal_array(
                     list(td.items.values())),
                                         fallback=instance)
             return instance
     else:
         if self.third_pass:
             self.fail(errorcode.INVALID_TYPE_X(t.name), t)
             return AnyType(TypeOfAny.from_error)
         return AnyType(TypeOfAny.special_form)
Example #22
0
 def test_generic_unbound_type(self):
     u = UnboundType('Foo', [UnboundType('T'), AnyType()])
     assert_equal(str(u), 'Foo?[T?, Any]')
Example #23
0
 def visit_NameConstant(self, n: ast35.NameConstant) -> Type:
     return UnboundType(str(n.value))
Example #24
0
 def visit_unbound_type(self, t: UnboundType) -> Type:
     if t.optional:
         t.optional = False
         # We don't need to worry about double-wrapping Optionals or
         # wrapping Anys: Union simplification will take care of that.
         return UnionType.make_simplified_union([self.visit_unbound_type(t), NoneTyp()])
     sym = self.lookup(t.name, t)
     if sym is not None:
         if sym.node is None:
             # UNBOUND_IMPORTED can happen if an unknown name was imported.
             if sym.kind != UNBOUND_IMPORTED:
                 self.fail('Internal error (node is None, kind={})'.format(sym.kind), t)
             return AnyType()
         fullname = sym.node.fullname()
         if sym.kind == BOUND_TVAR:
             if len(t.args) > 0:
                 self.fail('Type variable "{}" used with arguments'.format(
                     t.name), t)
             assert sym.tvar_def is not None
             return TypeVarType(sym.tvar_def, t.line)
         elif fullname == 'builtins.None':
             if experiments.STRICT_OPTIONAL:
                 return NoneTyp(is_ret_type=t.is_ret_type)
             else:
                 return Void()
         elif fullname == 'typing.Any':
             return AnyType()
         elif fullname == 'typing.Tuple':
             if len(t.args) == 2 and isinstance(t.args[1], EllipsisType):
                 # Tuple[T, ...] (uniform, variable-length tuple)
                 node = self.lookup_fqn_func('builtins.tuple')
                 tuple_info = cast(TypeInfo, node.node)
                 return Instance(tuple_info, [t.args[0].accept(self)], t.line)
             return self.tuple_type(self.anal_array(t.args))
         elif fullname == 'typing.Union':
             items = self.anal_array(t.args)
             items = [item for item in items if not isinstance(item, Void)]
             return UnionType.make_union(items)
         elif fullname == 'typing.Optional':
             if len(t.args) != 1:
                 self.fail('Optional[...] must have exactly one type argument', t)
                 return AnyType()
             items = self.anal_array(t.args)
             if experiments.STRICT_OPTIONAL:
                 return UnionType.make_simplified_union([items[0], NoneTyp()])
             else:
                 # Without strict Optional checking Optional[t] is just an alias for t.
                 return items[0]
         elif fullname == 'typing.Callable':
             return self.analyze_callable_type(t)
         elif fullname == 'typing.Type':
             if len(t.args) == 0:
                 return TypeType(AnyType(), line=t.line)
             if len(t.args) != 1:
                 self.fail('Type[...] must have exactly one type argument', t)
             items = self.anal_array(t.args)
             item = items[0]
             return TypeType(item, line=t.line)
         elif sym.kind == TYPE_ALIAS:
             # TODO: Generic type aliases.
             return sym.type_override
         elif not isinstance(sym.node, TypeInfo):
             name = sym.fullname
             if name is None:
                 name = sym.node.name()
             if isinstance(sym.node, Var) and isinstance(sym.node.type, AnyType):
                 # Something with an Any type -- make it an alias for Any in a type
                 # context. This is slightly problematic as it allows using the type 'Any'
                 # as a base class -- however, this will fail soon at runtime so the problem
                 # is pretty minor.
                 return AnyType()
             self.fail('Invalid type "{}"'.format(name), t)
             return t
         info = sym.node  # type: TypeInfo
         if len(t.args) > 0 and info.fullname() == 'builtins.tuple':
             return TupleType(self.anal_array(t.args),
                              Instance(info, [AnyType()], t.line),
                              t.line)
         else:
             # Analyze arguments and construct Instance type. The
             # number of type arguments and their values are
             # checked only later, since we do not always know the
             # valid count at this point. Thus we may construct an
             # Instance with an invalid number of type arguments.
             instance = Instance(info, self.anal_array(t.args), t.line)
             tup = info.tuple_type
             if tup is None:
                 return instance
             else:
                 # The class has a Tuple[...] base class so it will be
                 # represented as a tuple type.
                 if t.args:
                     self.fail('Generic tuple types not supported', t)
                     return AnyType()
                 return tup.copy_modified(items=self.anal_array(tup.items),
                                          fallback=instance)
     else:
         return AnyType()
Example #25
0
def expr_to_unanalyzed_type(expr: Expression, _parent: Optional[Expression] = None) -> ProperType:
    """Translate an expression to the corresponding type.

    The result is not semantically analyzed. It can be UnboundType or TypeList.
    Raise TypeTranslationError if the expression cannot represent a type.
    """
    # The `parent` parameter is used in recursive calls to provide context for
    # understanding whether an CallableArgument is ok.
    name = None  # type: Optional[str]
    if isinstance(expr, NameExpr):
        name = expr.name
        if name == 'True':
            return RawExpressionType(True, 'builtins.bool', line=expr.line, column=expr.column)
        elif name == 'False':
            return RawExpressionType(False, 'builtins.bool', line=expr.line, column=expr.column)
        else:
            return UnboundType(name, line=expr.line, column=expr.column)
    elif isinstance(expr, MemberExpr):
        fullname = get_member_expr_fullname(expr)
        if fullname:
            return UnboundType(fullname, line=expr.line, column=expr.column)
        else:
            raise TypeTranslationError()
    elif isinstance(expr, IndexExpr):
        base = expr_to_unanalyzed_type(expr.base, expr)
        if isinstance(base, UnboundType):
            if base.args:
                raise TypeTranslationError()
            if isinstance(expr.index, TupleExpr):
                args = expr.index.items
            else:
                args = [expr.index]
            base.args = tuple(expr_to_unanalyzed_type(arg, expr) for arg in args)
            if not base.args:
                base.empty_tuple_index = True
            return base
        else:
            raise TypeTranslationError()
    elif isinstance(expr, CallExpr) and isinstance(_parent, ListExpr):
        c = expr.callee
        names = []
        # Go through the dotted member expr chain to get the full arg
        # constructor name to look up
        while True:
            if isinstance(c, NameExpr):
                names.append(c.name)
                break
            elif isinstance(c, MemberExpr):
                names.append(c.name)
                c = c.expr
            else:
                raise TypeTranslationError()
        arg_const = '.'.join(reversed(names))

        # Go through the constructor args to get its name and type.
        name = None
        default_type = AnyType(TypeOfAny.unannotated)
        typ = default_type  # type: Type
        for i, arg in enumerate(expr.args):
            if expr.arg_names[i] is not None:
                if expr.arg_names[i] == "name":
                    if name is not None:
                        # Two names
                        raise TypeTranslationError()
                    name = _extract_argument_name(arg)
                    continue
                elif expr.arg_names[i] == "type":
                    if typ is not default_type:
                        # Two types
                        raise TypeTranslationError()
                    typ = expr_to_unanalyzed_type(arg, expr)
                    continue
                else:
                    raise TypeTranslationError()
            elif i == 0:
                typ = expr_to_unanalyzed_type(arg, expr)
            elif i == 1:
                name = _extract_argument_name(arg)
            else:
                raise TypeTranslationError()
        return CallableArgument(typ, name, arg_const, expr.line, expr.column)
    elif isinstance(expr, ListExpr):
        return TypeList([expr_to_unanalyzed_type(t, expr) for t in expr.items],
                        line=expr.line, column=expr.column)
    elif isinstance(expr, StrExpr):
        return parse_type_string(expr.value, 'builtins.str', expr.line, expr.column,
                                 assume_str_is_unicode=expr.from_python_3)
    elif isinstance(expr, BytesExpr):
        return parse_type_string(expr.value, 'builtins.bytes', expr.line, expr.column,
                                 assume_str_is_unicode=False)
    elif isinstance(expr, UnicodeExpr):
        return parse_type_string(expr.value, 'builtins.unicode', expr.line, expr.column,
                                 assume_str_is_unicode=True)
    elif isinstance(expr, UnaryExpr):
        typ = expr_to_unanalyzed_type(expr.expr)
        if isinstance(typ, RawExpressionType):
            if isinstance(typ.literal_value, int) and expr.op == '-':
                typ.literal_value *= -1
                return typ
        raise TypeTranslationError()
    elif isinstance(expr, IntExpr):
        return RawExpressionType(expr.value, 'builtins.int', line=expr.line, column=expr.column)
    elif isinstance(expr, FloatExpr):
        # Floats are not valid parameters for RawExpressionType , so we just
        # pass in 'None' for now. We'll report the appropriate error at a later stage.
        return RawExpressionType(None, 'builtins.float', line=expr.line, column=expr.column)
    elif isinstance(expr, ComplexExpr):
        # Same thing as above with complex numbers.
        return RawExpressionType(None, 'builtins.complex', line=expr.line, column=expr.column)
    elif isinstance(expr, EllipsisExpr):
        return EllipsisType(expr.line)
    else:
        raise TypeTranslationError()
Example #26
0
 def visit_Name(self, n: ast35.Name) -> Type:
     return UnboundType(n.id, line=self.line)
Example #27
0
 def visit_unbound_type(self, t: UnboundType) -> Type:
     if t.optional:
         t.optional = False
         # We don't need to worry about double-wrapping Optionals or
         # wrapping Anys: Union simplification will take care of that.
         return UnionType.make_simplified_union([self.visit_unbound_type(t), NoneTyp()])
     sym = self.lookup(t.name, t)
     if sym is not None:
         if sym.node is None:
             # UNBOUND_IMPORTED can happen if an unknown name was imported.
             if sym.kind != UNBOUND_IMPORTED:
                 self.fail('Internal error (node is None, kind={})'.format(sym.kind), t)
             return AnyType()
         fullname = sym.node.fullname()
         if sym.kind == BOUND_TVAR:
             if len(t.args) > 0:
                 self.fail('Type variable "{}" used with arguments'.format(
                     t.name), t)
             assert sym.tvar_def is not None
             return TypeVarType(sym.tvar_def, t.line)
         elif fullname == 'builtins.None':
             if experiments.STRICT_OPTIONAL:
                 return NoneTyp(is_ret_type=t.is_ret_type)
             else:
                 return Void()
         elif fullname == 'typing.Any':
             return AnyType()
         elif fullname == 'typing.Tuple':
             if len(t.args) == 0 and not t.empty_tuple_index:
                 # Bare 'Tuple' is same as 'tuple'
                 return self.builtin_type('builtins.tuple')
             if len(t.args) == 2 and isinstance(t.args[1], EllipsisType):
                 # Tuple[T, ...] (uniform, variable-length tuple)
                 instance = self.builtin_type('builtins.tuple', [t.args[0].accept(self)])
                 instance.line = t.line
                 return instance
             return self.tuple_type(self.anal_array(t.args))
         elif fullname == 'typing.Union':
             items = self.anal_array(t.args)
             items = [item for item in items if not isinstance(item, Void)]
             return UnionType.make_union(items)
         elif fullname == 'typing.Optional':
             if len(t.args) != 1:
                 self.fail('Optional[...] must have exactly one type argument', t)
                 return AnyType()
             items = self.anal_array(t.args)
             if experiments.STRICT_OPTIONAL:
                 return UnionType.make_simplified_union([items[0], NoneTyp()])
             else:
                 # Without strict Optional checking Optional[t] is just an alias for t.
                 return items[0]
         elif fullname == 'typing.Callable':
             return self.analyze_callable_type(t)
         elif fullname == 'typing.Type':
             if len(t.args) == 0:
                 return TypeType(AnyType(), line=t.line)
             if len(t.args) != 1:
                 self.fail('Type[...] must have exactly one type argument', t)
             items = self.anal_array(t.args)
             item = items[0]
             return TypeType(item, line=t.line)
         elif sym.kind == TYPE_ALIAS:
             override = sym.type_override
             an_args = self.anal_array(t.args)
             all_vars = self.get_type_var_names(override)
             exp_len = len(all_vars)
             act_len = len(an_args)
             if exp_len > 0 and act_len == 0:
                 # Interpret bare Alias same as normal generic, i.e., Alias[Any, Any, ...]
                 return self.replace_alias_tvars(override, all_vars, [AnyType()] * exp_len,
                                                 t.line, t.column)
             if exp_len == 0 and act_len == 0:
                 return override
             if act_len != exp_len:
                 self.fail('Bad number of arguments for type alias, expected: %s, given: %s'
                           % (exp_len, act_len), t)
                 return t
             return self.replace_alias_tvars(override, all_vars, an_args, t.line, t.column)
         elif not isinstance(sym.node, TypeInfo):
             name = sym.fullname
             if name is None:
                 name = sym.node.name()
             if isinstance(sym.node, Var) and isinstance(sym.node.type, AnyType):
                 # Something with an Any type -- make it an alias for Any in a type
                 # context. This is slightly problematic as it allows using the type 'Any'
                 # as a base class -- however, this will fail soon at runtime so the problem
                 # is pretty minor.
                 return AnyType()
             # Allow unbound type variables when defining an alias
             if not (self.aliasing and sym.kind == UNBOUND_TVAR):
                 self.fail('Invalid type "{}"'.format(name), t)
             return t
         info = sym.node  # type: TypeInfo
         if len(t.args) > 0 and info.fullname() == 'builtins.tuple':
             return TupleType(self.anal_array(t.args),
                              Instance(info, [AnyType()], t.line),
                              t.line)
         else:
             # Analyze arguments and construct Instance type. The
             # number of type arguments and their values are
             # checked only later, since we do not always know the
             # valid count at this point. Thus we may construct an
             # Instance with an invalid number of type arguments.
             instance = Instance(info, self.anal_array(t.args), t.line, t.column)
             tup = info.tuple_type
             if tup is not None:
                 # The class has a Tuple[...] base class so it will be
                 # represented as a tuple type.
                 if t.args:
                     self.fail('Generic tuple types not supported', t)
                     return AnyType()
                 return tup.copy_modified(items=self.anal_array(tup.items),
                                          fallback=instance)
             td = info.typeddict_type
             if td is not None:
                 # The class has a TypedDict[...] base class so it will be
                 # represented as a typeddict type.
                 if t.args:
                     self.fail('Generic TypedDict types not supported', t)
                     return AnyType()
                 # Create a named TypedDictType
                 return td.copy_modified(item_types=self.anal_array(list(td.items.values())),
                                         fallback=instance)
             return instance
     else:
         return AnyType()
Example #28
0
 def visit_unbound_type(self, t: UnboundType) -> Type:
     if t.optional:
         t.optional = False
         # We don't need to worry about double-wrapping Optionals or
         # wrapping Anys: Union simplification will take care of that.
         return make_optional_type(self.visit_unbound_type(t))
     sym = self.lookup(t.name, t)
     if sym is not None:
         if sym.node is None:
             # UNBOUND_IMPORTED can happen if an unknown name was imported.
             if sym.kind != UNBOUND_IMPORTED:
                 self.fail(
                     'Internal error (node is None, kind={})'.format(
                         sym.kind), t)
             return AnyType()
         fullname = sym.node.fullname()
         hook = self.plugin.get_type_analyze_hook(fullname)
         if hook:
             return hook(AnalyzeTypeContext(t, t, self))
         if (fullname in nongen_builtins and t.args and not sym.normalized
                 and not self.allow_unnormalized):
             self.fail(no_subscript_builtin_alias(fullname), t)
         tvar_def = self.tvar_scope.get_binding(sym)
         if sym.kind == TVAR and tvar_def is not None:
             if len(t.args) > 0:
                 self.fail(
                     'Type variable "{}" used with arguments'.format(
                         t.name), t)
             return TypeVarType(tvar_def, t.line)
         elif fullname == 'builtins.None':
             return NoneTyp()
         elif fullname == 'typing.Any' or fullname == 'builtins.Any':
             return AnyType(explicit=True)
         elif fullname == 'typing.Tuple':
             if len(t.args) == 0 and not t.empty_tuple_index:
                 # Bare 'Tuple' is same as 'tuple'
                 if 'generics' in self.options.disallow_any and not self.is_typeshed_stub:
                     self.fail(messages.BARE_GENERIC, t)
                 typ = self.named_type('builtins.tuple',
                                       line=t.line,
                                       column=t.column)
                 typ.from_generic_builtin = True
                 return typ
             if len(t.args) == 2 and isinstance(t.args[1], EllipsisType):
                 # Tuple[T, ...] (uniform, variable-length tuple)
                 instance = self.named_type('builtins.tuple',
                                            [self.anal_type(t.args[0])])
                 instance.line = t.line
                 return instance
             return self.tuple_type(self.anal_array(t.args))
         elif fullname == 'typing.Union':
             items = self.anal_array(t.args)
             return UnionType.make_union(items)
         elif fullname == 'typing.Optional':
             if len(t.args) != 1:
                 self.fail(
                     'Optional[...] must have exactly one type argument', t)
                 return AnyType()
             item = self.anal_type(t.args[0])
             return make_optional_type(item)
         elif fullname == 'typing.Callable':
             return self.analyze_callable_type(t)
         elif fullname == 'typing.Type':
             if len(t.args) == 0:
                 any_type = AnyType(from_omitted_generics=True,
                                    line=t.line,
                                    column=t.column)
                 return TypeType(any_type, line=t.line, column=t.column)
             if len(t.args) != 1:
                 self.fail('Type[...] must have exactly one type argument',
                           t)
             item = self.anal_type(t.args[0])
             return TypeType.make_normalized(item, line=t.line)
         elif fullname == 'typing.ClassVar':
             if self.nesting_level > 0:
                 self.fail(
                     'Invalid type: ClassVar nested inside other type', t)
             if len(t.args) == 0:
                 return AnyType(line=t.line)
             if len(t.args) != 1:
                 self.fail(
                     'ClassVar[...] must have at most one type argument', t)
                 return AnyType()
             item = self.anal_type(t.args[0])
             if isinstance(item, TypeVarType) or get_type_vars(item):
                 self.fail('Invalid type: ClassVar cannot be generic', t)
                 return AnyType()
             return item
         elif fullname in ('mypy_extensions.NoReturn', 'typing.NoReturn'):
             return UninhabitedType(is_noreturn=True)
         elif sym.kind == TYPE_ALIAS:
             override = sym.type_override
             all_vars = sym.alias_tvars
             assert override is not None
             an_args = self.anal_array(t.args)
             if all_vars is not None:
                 exp_len = len(all_vars)
             else:
                 exp_len = 0
             act_len = len(an_args)
             if exp_len > 0 and act_len == 0:
                 # Interpret bare Alias same as normal generic, i.e., Alias[Any, Any, ...]
                 assert all_vars is not None
                 return set_any_tvars(override, all_vars, t.line, t.column)
             if exp_len == 0 and act_len == 0:
                 return override
             if act_len != exp_len:
                 self.fail(
                     'Bad number of arguments for type alias, expected: %s, given: %s'
                     % (exp_len, act_len), t)
                 return set_any_tvars(override,
                                      all_vars or [],
                                      t.line,
                                      t.column,
                                      implicit=False)
             assert all_vars is not None
             return replace_alias_tvars(override, all_vars, an_args, t.line,
                                        t.column)
         elif not isinstance(sym.node, TypeInfo):
             name = sym.fullname
             if name is None:
                 name = sym.node.name()
             if isinstance(sym.node, Var) and isinstance(
                     sym.node.type, AnyType):
                 # Something with an Any type -- make it an alias for Any in a type
                 # context. This is slightly problematic as it allows using the type 'Any'
                 # as a base class -- however, this will fail soon at runtime so the problem
                 # is pretty minor.
                 return AnyType(from_unimported_type=True)
             # Allow unbound type variables when defining an alias
             if not (self.aliasing and sym.kind == TVAR
                     and self.tvar_scope.get_binding(sym) is None):
                 self.fail('Invalid type "{}"'.format(name), t)
             return t
         info = sym.node  # type: TypeInfo
         if len(t.args) > 0 and info.fullname() == 'builtins.tuple':
             return TupleType(self.anal_array(t.args),
                              Instance(info, [AnyType()], t.line), t.line)
         else:
             # Analyze arguments and construct Instance type. The
             # number of type arguments and their values are
             # checked only later, since we do not always know the
             # valid count at this point. Thus we may construct an
             # Instance with an invalid number of type arguments.
             instance = Instance(info, self.anal_array(t.args), t.line,
                                 t.column)
             instance.from_generic_builtin = sym.normalized
             tup = info.tuple_type
             if tup is not None:
                 # The class has a Tuple[...] base class so it will be
                 # represented as a tuple type.
                 if t.args:
                     self.fail('Generic tuple types not supported', t)
                     return AnyType()
                 return tup.copy_modified(items=self.anal_array(tup.items),
                                          fallback=instance)
             td = info.typeddict_type
             if td is not None:
                 # The class has a TypedDict[...] base class so it will be
                 # represented as a typeddict type.
                 if t.args:
                     self.fail('Generic TypedDict types not supported', t)
                     return AnyType()
                 # Create a named TypedDictType
                 return td.copy_modified(item_types=self.anal_array(
                     list(td.items.values())),
                                         fallback=instance)
             return instance
     else:
         return AnyType()
Example #29
0
 def __init__(self):
     super().__init__()
     self.x = UnboundType('X')  # Helpers
     self.y = UnboundType('Y')
     self.fx = TypeFixture()
     self.function = self.fx.function
Example #30
0
 def visit_unbound_type(self, t: UnboundType) -> Type:
     if t.optional:
         t.optional = False
         # We don't need to worry about double-wrapping Optionals or
         # wrapping Anys: Union simplification will take care of that.
         return UnionType.make_simplified_union(
             [self.visit_unbound_type(t),
              NoneTyp()])
     sym = self.lookup(t.name, t)
     if sym is not None:
         if sym.node is None:
             # UNBOUND_IMPORTED can happen if an unknown name was imported.
             if sym.kind != UNBOUND_IMPORTED:
                 self.fail(
                     'Internal error (node is None, kind={})'.format(
                         sym.kind), t)
             return AnyType()
         fullname = sym.node.fullname()
         if sym.kind == BOUND_TVAR:
             if len(t.args) > 0:
                 self.fail(
                     'Type variable "{}" used with arguments'.format(
                         t.name), t)
             assert sym.tvar_def is not None
             return TypeVarType(sym.tvar_def, t.line)
         elif fullname == 'builtins.None':
             if experiments.STRICT_OPTIONAL:
                 return NoneTyp(is_ret_type=t.is_ret_type)
             else:
                 return Void()
         elif fullname == 'typing.Any':
             return AnyType()
         elif fullname == 'typing.Tuple':
             if len(t.args) == 0 and not t.empty_tuple_index:
                 # Bare 'Tuple' is same as 'tuple'
                 return self.builtin_type('builtins.tuple')
             if len(t.args) == 2 and isinstance(t.args[1], EllipsisType):
                 # Tuple[T, ...] (uniform, variable-length tuple)
                 instance = self.builtin_type('builtins.tuple',
                                              [t.args[0].accept(self)])
                 instance.line = t.line
                 return instance
             return self.tuple_type(self.anal_array(t.args))
         elif fullname == 'typing.Union':
             items = self.anal_array(t.args)
             items = [item for item in items if not isinstance(item, Void)]
             return UnionType.make_union(items)
         elif fullname == 'typing.Optional':
             if len(t.args) != 1:
                 self.fail(
                     'Optional[...] must have exactly one type argument', t)
                 return AnyType()
             items = self.anal_array(t.args)
             if experiments.STRICT_OPTIONAL:
                 return UnionType.make_simplified_union(
                     [items[0], NoneTyp()])
             else:
                 # Without strict Optional checking Optional[t] is just an alias for t.
                 return items[0]
         elif fullname == 'typing.Callable':
             return self.analyze_callable_type(t)
         elif fullname == 'typing.Type':
             if len(t.args) == 0:
                 return TypeType(AnyType(), line=t.line)
             if len(t.args) != 1:
                 self.fail('Type[...] must have exactly one type argument',
                           t)
             items = self.anal_array(t.args)
             item = items[0]
             return TypeType(item, line=t.line)
         elif sym.kind == TYPE_ALIAS:
             override = sym.type_override
             an_args = self.anal_array(t.args)
             all_vars = self.get_type_var_names(override)
             exp_len = len(all_vars)
             act_len = len(an_args)
             if exp_len > 0 and act_len == 0:
                 # Interpret bare Alias same as normal generic, i.e., Alias[Any, Any, ...]
                 return self.replace_alias_tvars(override, all_vars,
                                                 [AnyType()] * exp_len,
                                                 t.line, t.column)
             if exp_len == 0 and act_len == 0:
                 return override
             if act_len != exp_len:
                 self.fail(
                     'Bad number of arguments for type alias, expected: %s, given: %s'
                     % (exp_len, act_len), t)
                 return t
             return self.replace_alias_tvars(override, all_vars, an_args,
                                             t.line, t.column)
         elif not isinstance(sym.node, TypeInfo):
             name = sym.fullname
             if name is None:
                 name = sym.node.name()
             if isinstance(sym.node, Var) and isinstance(
                     sym.node.type, AnyType):
                 # Something with an Any type -- make it an alias for Any in a type
                 # context. This is slightly problematic as it allows using the type 'Any'
                 # as a base class -- however, this will fail soon at runtime so the problem
                 # is pretty minor.
                 return AnyType()
             # Allow unbound type variables when defining an alias
             if not (self.aliasing and sym.kind == UNBOUND_TVAR):
                 self.fail('Invalid type "{}"'.format(name), t)
             return t
         info = sym.node  # type: TypeInfo
         if len(t.args) > 0 and info.fullname() == 'builtins.tuple':
             return TupleType(self.anal_array(t.args),
                              Instance(info, [AnyType()], t.line), t.line)
         else:
             # Analyze arguments and construct Instance type. The
             # number of type arguments and their values are
             # checked only later, since we do not always know the
             # valid count at this point. Thus we may construct an
             # Instance with an invalid number of type arguments.
             instance = Instance(info, self.anal_array(t.args), t.line,
                                 t.column)
             tup = info.tuple_type
             if tup is None:
                 return instance
             else:
                 # The class has a Tuple[...] base class so it will be
                 # represented as a tuple type.
                 if t.args:
                     self.fail('Generic tuple types not supported', t)
                     return AnyType()
                 return tup.copy_modified(items=self.anal_array(tup.items),
                                          fallback=instance)
     else:
         return AnyType()
Example #31
0
 def test_generic_unbound_type(self) -> None:
     u = UnboundType('Foo',
                     [UnboundType('T'),
                      AnyType(TypeOfAny.special_form)])
     assert_equal(str(u), 'Foo?[T?, Any]')
Example #32
0
 def test_simple_unbound_type(self) -> None:
     u = UnboundType('Foo')
     assert_equal(str(u), 'Foo?')
Example #33
0
 def setUp(self) -> None:
     self.x = UnboundType('X')  # Helpers
     self.y = UnboundType('Y')
     self.fx = TypeFixture()
     self.function = self.fx.function
Example #34
0
    def visit_file(self, file: MypyFile, fnam: str, mod_id: str,
                   options: Options) -> None:
        """Perform the first analysis pass.

        Populate module global table.  Resolve the full names of
        definitions not nested within functions and construct type
        info structures, but do not resolve inter-definition
        references such as base classes.

        Also add implicit definitions such as __name__.

        In this phase we don't resolve imports. For 'from ... import',
        we generate dummy symbol table nodes for the imported names,
        and these will get resolved in later phases of semantic
        analysis.
        """
        sem = self.sem
        self.sem.options = options  # Needed because we sometimes call into it
        self.pyversion = options.python_version
        self.platform = options.platform
        sem.cur_mod_id = mod_id
        sem.cur_mod_node = file
        sem.errors.set_file(fnam, mod_id, scope=sem.scope)
        sem.globals = SymbolTable()
        sem.global_decls = [set()]
        sem.nonlocal_decls = [set()]
        sem.block_depth = [0]

        sem.scope.enter_file(mod_id)

        defs = file.defs

        with experiments.strict_optional_set(options.strict_optional):
            # Add implicit definitions of module '__name__' etc.
            for name, t in implicit_module_attrs.items():
                # unicode docstrings should be accepted in Python 2
                if name == '__doc__':
                    if self.pyversion >= (3, 0):
                        typ = UnboundType('__builtins__.str')  # type: Type
                    else:
                        typ = UnionType([
                            UnboundType('__builtins__.str'),
                            UnboundType('__builtins__.unicode')
                        ])
                else:
                    assert t is not None, 'type should be specified for {}'.format(
                        name)
                    typ = UnboundType(t)
                v = Var(name, typ)
                v._fullname = self.sem.qualified_name(name)
                self.sem.globals[name] = SymbolTableNode(GDEF, v)

            for d in defs:
                d.accept(self)

            # Add implicit definition of literals/keywords to builtins, as we
            # cannot define a variable with them explicitly.
            if mod_id == 'builtins':
                literal_types = [
                    ('None', NoneTyp()),
                    # reveal_type is a mypy-only function that gives an error with
                    # the type of its arg.
                    ('reveal_type', AnyType(TypeOfAny.special_form)),
                    # reveal_locals is a mypy-only function that gives an error with the types of
                    # locals
                    ('reveal_locals', AnyType(TypeOfAny.special_form)),
                ]  # type: List[Tuple[str, Type]]

                # TODO(ddfisher): This guard is only needed because mypy defines
                # fake builtins for its tests which often don't define bool.  If
                # mypy is fast enough that we no longer need those, this
                # conditional check should be removed.
                if 'bool' in self.sem.globals:
                    bool_type = self.sem.named_type('bool')
                    literal_types.extend([
                        ('True', bool_type),
                        ('False', bool_type),
                        ('__debug__', bool_type),
                    ])
                else:
                    # We are running tests without 'bool' in builtins.
                    # TODO: Find a permanent solution to this problem.
                    # Maybe add 'bool' to all fixtures?
                    literal_types.append(
                        ('True', AnyType(TypeOfAny.special_form)))

                for name, typ in literal_types:
                    v = Var(name, typ)
                    v._fullname = self.sem.qualified_name(name)
                    self.sem.globals[name] = SymbolTableNode(GDEF, v)

            del self.sem.options

        sem.scope.leave()
Example #35
0
 def visit_unbound_type(self, t: UnboundType) -> Type:
     if t.optional:
         t.optional = False
         # We don't need to worry about double-wrapping Optionals or
         # wrapping Anys: Union simplification will take care of that.
         return make_optional_type(self.visit_unbound_type(t))
     sym = self.lookup(t.name, t, suppress_errors=self.third_pass)  # type: ignore
     if sym is not None:
         if sym.node is None:
             # UNBOUND_IMPORTED can happen if an unknown name was imported.
             if sym.kind != UNBOUND_IMPORTED:
                 self.fail('Internal error (node is None, kind={})'.format(sym.kind), t)
             return AnyType(TypeOfAny.special_form)
         fullname = sym.node.fullname()
         hook = self.plugin.get_type_analyze_hook(fullname)
         if hook:
             return hook(AnalyzeTypeContext(t, t, self))
         if (fullname in nongen_builtins and t.args and
                 not sym.normalized and not self.allow_unnormalized):
             self.fail(no_subscript_builtin_alias(fullname), t)
         if self.tvar_scope:
             tvar_def = self.tvar_scope.get_binding(sym)
         else:
             tvar_def = None
         if self.warn_bound_tvar and sym.kind == TVAR and tvar_def is not None:
             self.fail('Can\'t use bound type variable "{}"'
                       ' to define generic alias'.format(t.name), t)
             return AnyType(TypeOfAny.from_error)
         elif sym.kind == TVAR and tvar_def is not None:
             if len(t.args) > 0:
                 self.fail('Type variable "{}" used with arguments'.format(
                     t.name), t)
             return TypeVarType(tvar_def, t.line)
         elif fullname == 'builtins.None':
             return NoneTyp()
         elif fullname == 'typing.Any' or fullname == 'builtins.Any':
             return AnyType(TypeOfAny.explicit)
         elif fullname == 'typing.Tuple':
             if len(t.args) == 0 and not t.empty_tuple_index:
                 # Bare 'Tuple' is same as 'tuple'
                 if self.options.disallow_any_generics and not self.is_typeshed_stub:
                     self.fail(messages.BARE_GENERIC, t)
                 typ = self.named_type('builtins.tuple', line=t.line, column=t.column)
                 typ.from_generic_builtin = True
                 return typ
             if len(t.args) == 2 and isinstance(t.args[1], EllipsisType):
                 # Tuple[T, ...] (uniform, variable-length tuple)
                 instance = self.named_type('builtins.tuple', [self.anal_type(t.args[0])])
                 instance.line = t.line
                 return instance
             return self.tuple_type(self.anal_array(t.args))
         elif fullname == 'typing.Union':
             items = self.anal_array(t.args)
             return UnionType.make_union(items)
         elif fullname == 'typing.Optional':
             if len(t.args) != 1:
                 self.fail('Optional[...] must have exactly one type argument', t)
                 return AnyType(TypeOfAny.from_error)
             item = self.anal_type(t.args[0])
             return make_optional_type(item)
         elif fullname == 'typing.Callable':
             return self.analyze_callable_type(t)
         elif fullname == 'typing.Type':
             if len(t.args) == 0:
                 any_type = AnyType(TypeOfAny.from_omitted_generics,
                                    line=t.line, column=t.column)
                 return TypeType(any_type, line=t.line, column=t.column)
             if len(t.args) != 1:
                 self.fail('Type[...] must have exactly one type argument', t)
             item = self.anal_type(t.args[0])
             return TypeType.make_normalized(item, line=t.line)
         elif fullname == 'typing.ClassVar':
             if self.nesting_level > 0:
                 self.fail('Invalid type: ClassVar nested inside other type', t)
             if len(t.args) == 0:
                 return AnyType(TypeOfAny.from_omitted_generics, line=t.line, column=t.column)
             if len(t.args) != 1:
                 self.fail('ClassVar[...] must have at most one type argument', t)
                 return AnyType(TypeOfAny.from_error)
             item = self.anal_type(t.args[0])
             if isinstance(item, TypeVarType) or get_type_vars(item):
                 self.fail('Invalid type: ClassVar cannot be generic', t)
                 return AnyType(TypeOfAny.from_error)
             return item
         elif fullname in ('mypy_extensions.NoReturn', 'typing.NoReturn'):
             return UninhabitedType(is_noreturn=True)
         elif sym.kind == TYPE_ALIAS:
             override = sym.type_override
             all_vars = sym.alias_tvars
             assert override is not None
             an_args = self.anal_array(t.args)
             if all_vars is not None:
                 exp_len = len(all_vars)
             else:
                 exp_len = 0
             act_len = len(an_args)
             if exp_len > 0 and act_len == 0:
                 # Interpret bare Alias same as normal generic, i.e., Alias[Any, Any, ...]
                 assert all_vars is not None
                 return set_any_tvars(override, all_vars, t.line, t.column)
             if exp_len == 0 and act_len == 0:
                 return override
             if act_len != exp_len:
                 self.fail('Bad number of arguments for type alias, expected: %s, given: %s'
                           % (exp_len, act_len), t)
                 return set_any_tvars(override, all_vars or [],
                                      t.line, t.column, implicit=False)
             assert all_vars is not None
             return replace_alias_tvars(override, all_vars, an_args, t.line, t.column)
         elif not isinstance(sym.node, TypeInfo):
             name = sym.fullname
             if name is None:
                 name = sym.node.name()
             if isinstance(sym.node, Var) and isinstance(sym.node.type, AnyType):
                 # Something with an Any type -- make it an alias for Any in a type
                 # context. This is slightly problematic as it allows using the type 'Any'
                 # as a base class -- however, this will fail soon at runtime so the problem
                 # is pretty minor.
                 return AnyType(TypeOfAny.from_unimported_type)
             # Allow unbound type variables when defining an alias
             if not (self.aliasing and sym.kind == TVAR and
                     (not self.tvar_scope or self.tvar_scope.get_binding(sym) is None)):
                 if (not self.third_pass and not self.in_dynamic_func and
                         not (isinstance(sym.node, (FuncDef, Decorator)) or
                              isinstance(sym.node, Var) and sym.node.is_ready) and
                         not (sym.kind == TVAR and tvar_def is None)):
                     if t.args and not self.global_scope:
                         self.fail('Unsupported forward reference to "{}"'.format(t.name), t)
                         return AnyType(TypeOfAny.from_error)
                     return ForwardRef(t)
                 self.fail('Invalid type "{}"'.format(name), t)
                 if self.third_pass and sym.kind == TVAR:
                     self.note_func("Forward references to type variables are prohibited", t)
             return t
         info = sym.node  # type: TypeInfo
         if len(t.args) > 0 and info.fullname() == 'builtins.tuple':
             fallback = Instance(info, [AnyType(TypeOfAny.special_form)], t.line)
             return TupleType(self.anal_array(t.args), fallback, t.line)
         else:
             # Analyze arguments and construct Instance type. The
             # number of type arguments and their values are
             # checked only later, since we do not always know the
             # valid count at this point. Thus we may construct an
             # Instance with an invalid number of type arguments.
             instance = Instance(info, self.anal_array(t.args), t.line, t.column)
             instance.from_generic_builtin = sym.normalized
             tup = info.tuple_type
             if tup is not None:
                 # The class has a Tuple[...] base class so it will be
                 # represented as a tuple type.
                 if t.args:
                     self.fail('Generic tuple types not supported', t)
                     return AnyType(TypeOfAny.from_error)
                 return tup.copy_modified(items=self.anal_array(tup.items),
                                          fallback=instance)
             td = info.typeddict_type
             if td is not None:
                 # The class has a TypedDict[...] base class so it will be
                 # represented as a typeddict type.
                 if t.args:
                     self.fail('Generic TypedDict types not supported', t)
                     return AnyType(TypeOfAny.from_error)
                 # Create a named TypedDictType
                 return td.copy_modified(item_types=self.anal_array(list(td.items.values())),
                                         fallback=instance)
             return instance
     else:
         if self.third_pass:
             self.fail('Invalid type "{}"'.format(t.name), t)
             return AnyType(TypeOfAny.from_error)
         return AnyType(TypeOfAny.special_form)