Пример #1
0
 def visit_symbol_table(self, symtab: SymbolTable,
                        table_fullname: str) -> None:
     # Copy the items because we may mutate symtab.
     for key, value in list(symtab.items()):
         cross_ref = value.cross_ref
         if cross_ref is not None:  # Fix up cross-reference.
             value.cross_ref = None
             if cross_ref in self.modules:
                 value.node = self.modules[cross_ref]
             else:
                 stnode = lookup_fully_qualified(
                     cross_ref,
                     self.modules,
                     raise_on_missing=not self.allow_missing)
                 if stnode is not None:
                     assert stnode.node is not None, (table_fullname + "." +
                                                      key, cross_ref)
                     value.node = stnode.node
                 elif not self.allow_missing:
                     assert False, "Could not find cross-ref %s" % (
                         cross_ref, )
                 else:
                     # We have a missing crossref in allow missing mode, need to put something
                     value.node = missing_info(self.modules)
         else:
             if isinstance(value.node, TypeInfo):
                 # TypeInfo has no accept().  TODO: Add it?
                 self.visit_type_info(value.node)
             elif value.node is not None:
                 value.node.accept(self)
             else:
                 assert False, 'Unexpected empty node %r: %s' % (key, value)
Пример #2
0
 def visit_typeddict_type(self, tdt: TypedDictType) -> None:
     if tdt.items:
         for it in tdt.items.values():
             it.accept(self)
     if tdt.fallback is not None:
         if tdt.fallback.type_ref is not None:
             if lookup_fully_qualified(tdt.fallback.type_ref, self.modules,
                                       raise_on_missing=not self.allow_missing) is None:
                 # We reject fake TypeInfos for TypedDict fallbacks because
                 # the latter are used in type checking and must be valid.
                 tdt.fallback.type_ref = 'typing._TypedDict'
         tdt.fallback.accept(self)
Пример #3
0
def lookup_fully_qualified_alias(modules: Dict[str, MypyFile], name: str, *,
                                 allow_missing: bool) -> TypeAlias:
    stnode = lookup_fully_qualified(name, modules, raise_on_missing=not allow_missing)
    node = stnode.node if stnode else None
    if isinstance(node, TypeAlias):
        return node
    else:
        # Looks like a missing TypeAlias during an initial daemon load, put something there
        assert allow_missing, "Should never get here in normal mode," \
                              " got {}:{} instead of TypeAlias".format(type(node).__name__,
                                                                       node.fullname if node
                                                                       else '')
        return missing_alias()
Пример #4
0
    def argument(self, ctx: 'mypy.plugin.ClassDefContext') -> Argument:
        """Return this attribute as an argument to __init__."""
        assert self.init

        init_type = self.init_type or self.info[self.name].type

        if self.converter.name:
            # When a converter is set the init_type is overridden by the first argument
            # of the converter method.
            converter = lookup_fully_qualified(self.converter.name,
                                               ctx.api.modules,
                                               raise_on_missing=False)
            if not converter:
                # The converter may be a local variable. Check there too.
                converter = ctx.api.lookup_qualified(self.converter.name,
                                                     self.info, True)

            # Get the type of the converter.
            converter_type: Optional[Type] = None
            if converter and isinstance(converter.node, TypeInfo):
                from mypy.checkmember import type_object_type  # To avoid import cycle.
                converter_type = type_object_type(converter.node,
                                                  ctx.api.named_type)
            elif converter and isinstance(converter.node, OverloadedFuncDef):
                converter_type = converter.node.type
            elif converter and converter.type:
                converter_type = converter.type

            init_type = None
            converter_type = get_proper_type(converter_type)
            if isinstance(converter_type,
                          CallableType) and converter_type.arg_types:
                init_type = ctx.api.anal_type(converter_type.arg_types[0])
            elif isinstance(converter_type, Overloaded):
                types: List[Type] = []
                for item in converter_type.items:
                    # Walk the overloads looking for methods that can accept one argument.
                    num_arg_types = len(item.arg_types)
                    if not num_arg_types:
                        continue
                    if num_arg_types > 1 and any(
                            kind == ARG_POS for kind in item.arg_kinds[1:]):
                        continue
                    types.append(item.arg_types[0])
                # Make a union of all the valid types.
                if types:
                    args = make_simplified_union(types)
                    init_type = ctx.api.anal_type(args)

            if self.converter.is_attr_converters_optional and init_type:
                # If the converter was attr.converter.optional(type) then add None to
                # the allowed init_type.
                init_type = UnionType.make_union([init_type, NoneType()])

            if not init_type:
                ctx.api.fail("Cannot determine __init__ type from converter",
                             self.context)
                init_type = AnyType(TypeOfAny.from_error)
        elif self.converter.name == '':
            # This means we had a converter but it's not of a type we can infer.
            # Error was shown in _get_converter_name
            init_type = AnyType(TypeOfAny.from_error)

        if init_type is None:
            if ctx.api.options.disallow_untyped_defs:
                # This is a compromise.  If you don't have a type here then the
                # __init__ will be untyped. But since the __init__ is added it's
                # pointing at the decorator. So instead we also show the error in the
                # assignment, which is where you would fix the issue.
                node = self.info[self.name].node
                assert node is not None
                ctx.api.msg.need_annotation_for_var(node, self.context)

            # Convert type not set to Any.
            init_type = AnyType(TypeOfAny.unannotated)

        if self.kw_only:
            arg_kind = ARG_NAMED_OPT if self.has_default else ARG_NAMED
        else:
            arg_kind = ARG_OPT if self.has_default else ARG_POS

        # Attrs removes leading underscores when creating the __init__ arguments.
        return Argument(Var(self.name.lstrip("_"), init_type), init_type, None,
                        arg_kind)
Пример #5
0
 def lookup_fully_qualified(self,
                            fullname: str) -> Optional[SymbolTableNode]:
     assert self._modules is not None
     return lookup_fully_qualified(fullname, self._modules)
Пример #6
0
def lookup_qualified_stnode(modules: Dict[str, MypyFile], name: str,
                            allow_missing: bool) -> Optional[SymbolTableNode]:
    return lookup_fully_qualified(name,
                                  modules,
                                  raise_on_missing=not allow_missing)
Пример #7
0
 def lookup_fully_qualified(self, fullname: str) -> Optional[SymbolTableNode]:
     assert self._modules is not None
     return lookup_fully_qualified(fullname, self._modules)
Пример #8
0
def lookup_qualified_stnode(modules: Dict[str, MypyFile], name: str,
                            quick_and_dirty: bool) -> Optional[SymbolTableNode]:
    return lookup_fully_qualified(name, modules, raise_on_missing=not quick_and_dirty)