Exemple #1
0
    def visit_instance(self, t: Instance) -> str:
        if t.type is not None:
            s = t.type.fullname() or t.type.name() or None
        else:
            s = None
        if s is None:
            return '<???>'
        if s in reverse_builtin_aliases:
            s = reverse_builtin_aliases[s]

        mod_obj = split_target(self.graph, s)
        assert mod_obj
        mod, obj = mod_obj

        # If a class is imported into the current module, rewrite the reference
        # to point to the current module. This helps the annotation tool avoid
        # inserting redundant imports when a type has been reexported.
        if self.module:
            parts = obj.split('.')  # need to split the object part if it is a nested class
            tree = self.graph[self.module].tree
            if tree and parts[0] in tree.names:
                mod = self.module

        if (mod, obj) == ('builtins', 'tuple'):
            mod, obj = 'typing', 'Tuple[' + t.args[0].accept(self) + ', ...]'
        elif t.args != []:
            obj += '[{}]'.format(self.list_str(t.args))

        if mod == 'builtins':
            return obj
        else:
            delim = '.' if '.' not in obj else ':'
            return mod + delim + obj
Exemple #2
0
    def visit_instance(self, t: Instance) -> str:
        if t.type is not None:
            s = t.type.fullname() or t.type.name() or None
        else:
            s = None
        if s is None:
            return '<???>'
        if s in reverse_builtin_aliases:
            s = reverse_builtin_aliases[s]

        mod_obj = split_target(self.graph, s)
        assert mod_obj
        mod, obj = mod_obj

        # If a class is imported into the current module, rewrite the reference
        # to point to the current module. This helps the annotation tool avoid
        # inserting redundant imports when a type has been reexported.
        if self.module:
            parts = obj.split(
                '.')  # need to split the object part if it is a nested class
            tree = self.graph[self.module].tree
            if tree and parts[0] in tree.names:
                mod = self.module

        if (mod, obj) == ('builtins', 'tuple'):
            mod, obj = 'typing', 'Tuple[' + t.args[0].accept(self) + ', ...]'
        elif t.args != []:
            obj += '[{}]'.format(self.list_str(t.args))

        if mod == 'builtins':
            return obj
        else:
            delim = '.' if '.' not in obj else ':'
            return mod + delim + obj
def lookup_target(modules: Dict[str, MypyFile],
                  target: str) -> List[DeferredNode]:
    """Look up a target by fully-qualified name."""
    module, rest = split_target(modules, target)
    if rest:
        components = rest.split('.')
    else:
        components = []
    node = modules[module]  # type: Optional[SymbolNode]
    file = None  # type: Optional[MypyFile]
    active_class = None
    active_class_name = None
    for c in components:
        if isinstance(node, TypeInfo):
            active_class = node
            active_class_name = node.name()
        # TODO: Is it possible for the assertion to fail?
        if isinstance(node, MypyFile):
            file = node
        assert isinstance(node, (MypyFile, TypeInfo))
        node = node.names[c].node
    if isinstance(node, TypeInfo):
        # A ClassDef target covers the body of the class and everything defined
        # within it.  To get the body we include the entire surrounding target,
        # typically a module top-level, since we don't support processing class
        # bodies as separate entitites for simplicity.
        assert file is not None
        result = [DeferredNode(file, None, None)]
        for name, symnode in node.names.items():
            node = symnode.node
            if isinstance(node, FuncDef):
                result.extend(lookup_target(modules, target + '.' + name))
        return result
    assert isinstance(node, (FuncDef, MypyFile))
    return [DeferredNode(node, active_class_name, active_class)]
Exemple #4
0
    def find_node(self, key: str) -> Tuple[str, str, FuncDef]:
        """From a target name, return module/target names and the func def."""
        # TODO: Also return OverloadedFuncDef -- currently these are ignored.
        graph = self.fgmanager.graph
        target = split_target(graph, key)
        if not target:
            raise SuggestionFailure("Cannot find module for %s" % (key, ))
        modname, tail = target

        tree = self.ensure_loaded(graph[modname])

        # N.B. This is reimplemented from update's lookup_target
        # basically just to produce better error messages.

        names = tree.names  # type: SymbolTable

        # Look through any classes
        components = tail.split('.')
        for i, component in enumerate(components[:-1]):
            if component not in names:
                raise SuggestionFailure(
                    "Unknown class %s.%s" %
                    (modname, '.'.join(components[:i + 1])))
            node = names[component].node  # type: Optional[SymbolNode]
            if not isinstance(node, TypeInfo):
                raise SuggestionFailure(
                    "Object %s.%s is not a class" %
                    (modname, '.'.join(components[:i + 1])))
            names = node.names

        # Look for the actual function/method
        funcname = components[-1]
        if funcname not in names:
            raise SuggestionFailure(
                "Unknown %s %s" %
                ("method" if len(components) > 1 else "function", key))
        node = names[funcname].node
        if not isinstance(node, FuncDef):
            raise SuggestionFailure("Object %s is not a function" % key)

        return (modname, tail, node)
Exemple #5
0
    def find_node(self, key: str) -> Tuple[str, str, FuncDef]:
        """From a target name, return module/target names and the func def."""
        # TODO: Also return OverloadedFuncDef -- currently these are ignored.
        graph = self.fgmanager.graph
        target = split_target(graph, key)
        if not target:
            raise SuggestionFailure("Cannot find module for %s" % (key,))
        modname, tail = target

        tree = self.ensure_loaded(graph[modname])

        # N.B. This is reimplemented from update's lookup_target
        # basically just to produce better error messages.

        names = tree.names  # type: SymbolTable

        # Look through any classes
        components = tail.split('.')
        for i, component in enumerate(components[:-1]):
            if component not in names:
                raise SuggestionFailure("Unknown class %s.%s" %
                                        (modname, '.'.join(components[:i + 1])))
            node = names[component].node  # type: Optional[SymbolNode]
            if not isinstance(node, TypeInfo):
                raise SuggestionFailure("Object %s.%s is not a class" %
                                        (modname, '.'.join(components[:i + 1])))
            names = node.names

        # Look for the actual function/method
        funcname = components[-1]
        if funcname not in names:
            raise SuggestionFailure("Unknown %s %s" %
                                    ("method" if len(components) > 1 else "function", key))
        node = names[funcname].node
        if not isinstance(node, FuncDef):
            raise SuggestionFailure("Object %s is not a function" % key)

        return (modname, tail, node)
Exemple #6
0
def lookup_target(
        manager: BuildManager,
        target: str) -> Tuple[List[DeferredNode], Optional[TypeInfo]]:
    """Look up a target by fully-qualified name.

    The first item in the return tuple is a list of deferred nodes that
    needs to be reprocessed. If the target represents a TypeInfo corresponding
    to a protocol, return it as a second item in the return tuple, otherwise None.
    """
    def not_found() -> None:
        manager.log_fine_grained(
            "Can't find matching target for %s (stale dependency?)" % target)

    modules = manager.modules
    items = split_target(modules, target)
    if items is None:
        not_found()  # Stale dependency
        return [], None
    module, rest = items
    if rest:
        components = rest.split('.')
    else:
        components = []
    node = modules[module]  # type: Optional[SymbolNode]
    file = None  # type: Optional[MypyFile]
    active_class = None
    active_class_name = None
    for c in components:
        if isinstance(node, TypeInfo):
            active_class = node
            active_class_name = node.name()
        if isinstance(node, MypyFile):
            file = node
        if (not isinstance(node, (MypyFile, TypeInfo)) or c not in node.names):
            not_found()  # Stale dependency
            return [], None
        node = node.names[c].node
    if isinstance(node, TypeInfo):
        # A ClassDef target covers the body of the class and everything defined
        # within it.  To get the body we include the entire surrounding target,
        # typically a module top-level, since we don't support processing class
        # bodies as separate entitites for simplicity.
        assert file is not None
        if node.fullname() != target:
            # This is a reference to a different TypeInfo, likely due to a stale dependency.
            # Processing them would spell trouble -- for example, we could be refreshing
            # a deserialized TypeInfo with missing attributes.
            not_found()
            return [], None
        result = [DeferredNode(file, None, None)]
        stale_info = None  # type: Optional[TypeInfo]
        if node.is_protocol:
            stale_info = node
        for name, symnode in node.names.items():
            node = symnode.node
            if isinstance(node, FuncDef):
                method, _ = lookup_target(manager, target + '.' + name)
                result.extend(method)
        return result, stale_info
    if isinstance(node, Decorator):
        # Decorator targets actually refer to the function definition only.
        node = node.func
    if not isinstance(node, (FuncDef, MypyFile, OverloadedFuncDef)):
        # The target can't be refreshed. It's possible that the target was
        # changed to another type and we have a stale dependency pointing to it.
        not_found()
        return [], None
    if node.fullname() != target:
        # Stale reference points to something unexpected. We shouldn't process since the
        # context will be wrong and it could be a partially initialized deserialized node.
        not_found()
        return [], None
    return [DeferredNode(node, active_class_name, active_class)], None
Exemple #7
0
def lookup_target(manager: BuildManager,
                  target: str) -> List[DeferredNode]:
    """Look up a target by fully-qualified name."""

    def not_found() -> None:
        manager.log_fine_grained(
            "Can't find matching target for %s (stale dependency?)" % target)

    modules = manager.modules
    items = split_target(modules, target)
    if items is None:
        not_found()  # Stale dependency
        return []
    module, rest = items
    if rest:
        components = rest.split('.')
    else:
        components = []
    node = modules[module]  # type: Optional[SymbolNode]
    file = None  # type: Optional[MypyFile]
    active_class = None
    active_class_name = None
    for c in components:
        if isinstance(node, TypeInfo):
            active_class = node
            active_class_name = node.name()
        if isinstance(node, MypyFile):
            file = node
        if (not isinstance(node, (MypyFile, TypeInfo))
                or c not in node.names):
            not_found()  # Stale dependency
            return []
        node = node.names[c].node
    if isinstance(node, TypeInfo):
        # A ClassDef target covers the body of the class and everything defined
        # within it.  To get the body we include the entire surrounding target,
        # typically a module top-level, since we don't support processing class
        # bodies as separate entitites for simplicity.
        assert file is not None
        if node.fullname() != target:
            # This is a reference to a different TypeInfo, likely due to a stale dependency.
            # Processing them would spell trouble -- for example, we could be refreshing
            # a deserialized TypeInfo with missing attributes.
            not_found()
            return []
        result = [DeferredNode(file, None, None)]
        for name, symnode in node.names.items():
            node = symnode.node
            if isinstance(node, FuncDef):
                result.extend(lookup_target(manager, target + '.' + name))
        return result
    if isinstance(node, Decorator):
        # Decorator targets actually refer to the function definition only.
        node = node.func
    if not isinstance(node, (FuncDef,
                             MypyFile,
                             OverloadedFuncDef)):
        # The target can't be refreshed. It's possible that the target was
        # changed to another type and we have a stale dependency pointing to it.
        not_found()
        return []
    if node.fullname() != target:
        # Stale reference points to something unexpected. We shouldn't process since the
        # context will be wrong and it could be a partially initialized deserialized node.
        not_found()
        return []
    return [DeferredNode(node, active_class_name, active_class)]