示例#1
0
 def visit_newtype_expr(self, node: NewTypeExpr) -> NewTypeExpr:
     res = NewTypeExpr(node.name,
                       node.old_type,
                       line=node.line,
                       column=node.column)
     res.info = node.info
     return res
示例#2
0
    def process_newtype_declaration(self, s: AssignmentStmt) -> None:
        """Check if s declares a NewType; if yes, store it in symbol table."""
        # Extract and check all information from newtype declaration
        name, call = self.analyze_newtype_declaration(s)
        if name is None or call is None:
            return

        old_type = self.check_newtype_args(name, call, s)
        call.analyzed = NewTypeExpr(name,
                                    old_type,
                                    line=call.line,
                                    column=call.column)
        if old_type is None:
            return

        # Create the corresponding class definition if the aliased type is subtypeable
        if isinstance(old_type, TupleType):
            newtype_class_info = self.build_newtype_typeinfo(
                name, old_type, old_type.partial_fallback)
            newtype_class_info.tuple_type = old_type
        elif isinstance(old_type, Instance):
            if old_type.type.is_protocol:
                self.fail("NewType cannot be used with protocol classes", s)
            newtype_class_info = self.build_newtype_typeinfo(
                name, old_type, old_type)
        else:
            message = "Argument 2 to NewType(...) must be subclassable (got {})"
            self.fail(message.format(self.msg.format(old_type)), s)
            return

        check_for_explicit_any(old_type,
                               self.options,
                               self.api.is_typeshed_stub_file,
                               self.msg,
                               context=s)

        if self.options.disallow_any_unimported and has_any_from_unimported_type(
                old_type):
            self.msg.unimported_type_becomes_any("Argument 2 to NewType(...)",
                                                 old_type, s)

        # If so, add it to the symbol table.
        node = self.api.lookup(name, s)
        if node is None:
            self.fail("Could not find {} in current namespace".format(name), s)
            return
        # TODO: why does NewType work in local scopes despite always being of kind GDEF?
        node.kind = GDEF
        call.analyzed.info = node.node = newtype_class_info
示例#3
0
    def process_newtype_declaration(self, s: AssignmentStmt) -> bool:
        """Check if s declares a NewType; if yes, store it in symbol table.

        Return True if it's a NewType declaration. The current target may be
        deferred as a side effect if the base type is not ready, even if
        the return value is True.

        The logic in this function mostly copies the logic for visit_class_def()
        with a single (non-Generic) base.
        """
        name, call = self.analyze_newtype_declaration(s)
        if name is None or call is None:
            return False
        # OK, now we know this is a NewType. But the base type may be not ready yet,
        # add placeholder as we do for ClassDef.

        fullname = self.api.qualified_name(name)
        if (not call.analyzed or isinstance(call.analyzed, NewTypeExpr)
                and not call.analyzed.info):
            # Start from labeling this as a future class, as we do for normal ClassDefs.
            placeholder = PlaceholderNode(fullname,
                                          s,
                                          s.line,
                                          becomes_typeinfo=True)
            self.api.add_symbol(name, placeholder, s, can_defer=False)

        old_type, should_defer = self.check_newtype_args(name, call, s)
        if not call.analyzed:
            call.analyzed = NewTypeExpr(name,
                                        old_type,
                                        line=call.line,
                                        column=call.column)
        if old_type is None:
            if should_defer:
                # Base type is not ready.
                self.api.defer()
                return True

        # Create the corresponding class definition if the aliased type is subtypeable
        if isinstance(old_type, TupleType):
            newtype_class_info = self.build_newtype_typeinfo(
                name, old_type, old_type.partial_fallback)
            newtype_class_info.tuple_type = old_type
        elif isinstance(old_type, Instance):
            if old_type.type.is_protocol:
                self.fail("NewType cannot be used with protocol classes", s)
            newtype_class_info = self.build_newtype_typeinfo(
                name, old_type, old_type)
        else:
            if old_type is not None:
                message = "Argument 2 to NewType(...) must be subclassable (got {})"
                self.fail(message.format(self.msg.format(old_type)), s)
            # Otherwise the error was already reported.
            old_type = AnyType(TypeOfAny.from_error)
            object_type = self.api.named_type('__builtins__.object')
            newtype_class_info = self.build_newtype_typeinfo(
                name, old_type, object_type)
            newtype_class_info.fallback_to_any = True

        check_for_explicit_any(old_type,
                               self.options,
                               self.api.is_typeshed_stub_file,
                               self.msg,
                               context=s)

        if self.options.disallow_any_unimported and has_any_from_unimported_type(
                old_type):
            self.msg.unimported_type_becomes_any("Argument 2 to NewType(...)",
                                                 old_type, s)

        # If so, add it to the symbol table.
        assert isinstance(call.analyzed, NewTypeExpr)
        # As we do for normal classes, create the TypeInfo only once, then just
        # update base classes on next iterations (to get rid of placeholders there).
        if not call.analyzed.info:
            call.analyzed.info = newtype_class_info
        else:
            call.analyzed.info.bases = newtype_class_info.bases
        self.api.add_symbol(name, call.analyzed.info, s)
        newtype_class_info.line = s.line
        return True
示例#4
0
 def visit_newtype_expr(self, node: NewTypeExpr) -> NewTypeExpr:
     return NewTypeExpr(node.info)