예제 #1
0
    def analyze_namedtuple_classdef(self, defn: ClassDef, is_stub_file: bool
                                    ) -> Tuple[bool, Optional[TypeInfo]]:
        """Analyze if given class definition can be a named tuple definition.

        Return a tuple where first item indicates whether this can possibly be a named tuple,
        and the second item is the corresponding TypeInfo (may be None if not ready and should be
        deferred).
        """
        for base_expr in defn.base_type_exprs:
            if isinstance(base_expr, RefExpr):
                self.api.accept(base_expr)
                if base_expr.fullname == 'typing.NamedTuple':
                    result = self.check_namedtuple_classdef(defn, is_stub_file)
                    if result is None:
                        # This is a valid named tuple, but some types are incomplete.
                        return True, None
                    items, types, default_items = result
                    info = self.build_namedtuple_typeinfo(
                        defn.name, items, types, default_items, defn.line)
                    defn.info = info
                    defn.analyzed = NamedTupleExpr(info, is_typed=True)
                    defn.analyzed.line = defn.line
                    defn.analyzed.column = defn.column
                    # All done: this is a valid named tuple with all types known.
                    return True, info
        # This can't be a valid named tuple.
        return False, None
예제 #2
0
    def check_namedtuple(self, node: Expression, var_name: Optional[str],
                         is_func_scope: bool) -> Optional[TypeInfo]:
        """Check if a call defines a namedtuple.

        The optional var_name argument is the name of the variable to
        which this is assigned, if any.

        If it does, return the corresponding TypeInfo. Return None otherwise.

        If the definition is invalid but looks like a namedtuple,
        report errors but return (some) TypeInfo.
        """
        if not isinstance(node, CallExpr):
            return None
        call = node
        callee = call.callee
        if not isinstance(callee, RefExpr):
            return None
        fullname = callee.fullname
        if fullname == 'collections.namedtuple':
            is_typed = False
        elif fullname == 'typing.NamedTuple':
            is_typed = True
        else:
            return None
        items, types, defaults, ok = self.parse_namedtuple_args(call, fullname)
        if not ok:
            # Error. Construct dummy return value.
            return self.build_namedtuple_typeinfo('namedtuple', [], [], {})
        name = cast(StrExpr, call.args[0]).value
        if name != var_name or is_func_scope:
            # Give it a unique name derived from the line number.
            name += '@' + str(call.line)
        if len(defaults) > 0:
            default_items = {
                arg_name: default
                for arg_name, default in zip(items[-len(defaults):], defaults)
            }
        else:
            default_items = {}
        info = self.build_namedtuple_typeinfo(name, items, types,
                                              default_items)
        # Store it as a global just in case it would remain anonymous.
        # (Or in the nearest class if there is one.)
        stnode = SymbolTableNode(GDEF, info)
        self.api.add_symbol_table_node(name, stnode)
        call.analyzed = NamedTupleExpr(info, is_typed=is_typed)
        call.analyzed.set_line(call.line, call.column)
        return info
예제 #3
0
 def analyze_namedtuple_classdef(self, defn: ClassDef) -> Optional[TypeInfo]:
     # special case for NamedTuple
     for base_expr in defn.base_type_exprs:
         if isinstance(base_expr, RefExpr):
             self.api.accept(base_expr)
             if base_expr.fullname == 'typing.NamedTuple':
                 node = self.api.lookup(defn.name, defn)
                 if node is not None:
                     node.kind = GDEF  # TODO in process_namedtuple_definition also applies here
                     items, types, default_items = self.check_namedtuple_classdef(defn)
                     info = self.build_namedtuple_typeinfo(
                         defn.name, items, types, default_items)
                     node.node = info
                     defn.info.replaced = info
                     defn.info = info
                     defn.analyzed = NamedTupleExpr(info, is_typed=True)
                     defn.analyzed.line = defn.line
                     defn.analyzed.column = defn.column
                     return info
     return None
예제 #4
0
 def store_namedtuple_info(self, info: TypeInfo, name: str,
                           call: CallExpr, is_typed: bool) -> None:
     self.api.add_symbol(name, info, call)
     call.analyzed = NamedTupleExpr(info, is_typed=is_typed)
     call.analyzed.set_line(call.line, call.column)
예제 #5
0
 def visit_namedtuple_expr(self, node: NamedTupleExpr) -> Node:
     return NamedTupleExpr(node.info)
예제 #6
0
파일: astmerge.py 프로젝트: rheehot/mypy
 def visit_namedtuple_expr(self, node: NamedTupleExpr) -> None:
     super().visit_namedtuple_expr(node)
     node.info = self.fixup_and_reset_typeinfo(node.info)
     self.process_synthetic_type_info(node.info)
예제 #7
0
 def store_namedtuple_info(self, info: TypeInfo, name: str,
                           call: CallExpr, is_typed: bool) -> None:
     stnode = SymbolTableNode(GDEF, info)
     self.api.add_symbol_table_node(name, stnode)
     call.analyzed = NamedTupleExpr(info, is_typed=is_typed)
     call.analyzed.set_line(call.line, call.column)
예제 #8
0
 def visit_namedtuple_expr(self, node: NamedTupleExpr) -> None:
     super().visit_namedtuple_expr(node)
     node.info = self.fixup(node.info)
     self.process_type_info(node.info)
예제 #9
0
파일: astmerge.py 프로젝트: python/mypy
 def visit_namedtuple_expr(self, node: NamedTupleExpr) -> None:
     super().visit_namedtuple_expr(node)
     node.info = self.fixup_and_reset_typeinfo(node.info)
     self.process_synthetic_type_info(node.info)