コード例 #1
0
def touch_import_top(package, name_to_import, node):
    """Works like `does_tree_import` but adds an import statement at the
    top if it was not imported (but below any __future__ imports).

    Calling this multiple times adds them in reverse order.
        
    Based on lib2to3.fixer_util.touch_import()
    """
    root = find_root(node)

    if does_tree_import(package, name_to_import, root):
        return

    # Look for __future__ imports and insert below them
    found = False
    for name in [
            'absolute_import', 'division', 'print_function', 'unicode_literals'
    ]:
        if does_tree_import('__future__', name, root):
            found = True
            break
    if found:
        # At least one __future__ import. We want to loop until we've seen them
        # all.
        start, end = None, None
        for idx, node in enumerate(root.children):
            if check_future_import(node):
                start = idx
                # Start looping
                idx2 = start
                while node:
                    node = node.next_sibling
                    idx2 += 1
                    if not check_future_import(node):
                        end = idx2
                        break
                break
        assert start is not None
        assert end is not None
        insert_pos = end
    else:
        # No __future__ imports
        for idx, node in enumerate(root.children):
            if node.type == syms.simple_stmt:  # and node.children and node.children[0].type == token.STRING):
                break
        insert_pos = idx

    if package is None:
        import_ = Node(syms.import_name, [
            Leaf(token.NAME, u"import"),
            Leaf(token.NAME, name_to_import, prefix=u" ")
        ])
    else:
        import_ = FromImport(package,
                             [Leaf(token.NAME, name_to_import, prefix=u" ")])

    children = [import_, Newline()]
    root.insert_child(insert_pos, Node(syms.simple_stmt, children))
コード例 #2
0
def touch_import_top(package, name_to_import, node):
    """Works like `does_tree_import` but adds an import statement at the
    top if it was not imported (but below any __future__ imports).

    Calling this multiple times adds them in reverse order.
        
    Based on lib2to3.fixer_util.touch_import()
    """
    root = find_root(node)

    if does_tree_import(package, name_to_import, root):
        return

    # Look for __future__ imports and insert below them
    found = False
    for name in ['absolute_import', 'division', 'print_function',
                 'unicode_literals']:
        if does_tree_import('__future__', name, root):
            found = True
            break
    if found:
        # At least one __future__ import. We want to loop until we've seen them
        # all.
        start, end = None, None
        for idx, node in enumerate(root.children):
            if check_future_import(node):
                start = idx
                # Start looping
                idx2 = start
                while node:
                    node = node.next_sibling
                    idx2 += 1
                    if not check_future_import(node):
                        end = idx2
                        break
                break
        assert start is not None
        assert end is not None
        insert_pos = end
    else:
        # No __future__ imports
        for idx, node in enumerate(root.children):
            if node.type == syms.simple_stmt: # and node.children and node.children[0].type == token.STRING):
                break
        insert_pos = idx

    if package is None:
        import_ = Node(syms.import_name, [
            Leaf(token.NAME, u"import"),
            Leaf(token.NAME, name_to_import, prefix=u" ")
        ])
    else:
        import_ = FromImport(package, [Leaf(token.NAME, name_to_import, prefix=u" ")])

    children = [import_, Newline()]
    root.insert_child(insert_pos, Node(syms.simple_stmt, children))
コード例 #3
0
ファイル: fixer_util.py プロジェクト: CGTIC/Plone_SP
def future_import2(feature, node):
    """
    An alternative to future_import() which might not work ...
    """
    root = find_root(node)
    
    if does_tree_import(u"__future__", feature, node):
        return

    insert_pos = 0
    for idx, node in enumerate(root.children):
        if node.type == syms.simple_stmt and node.children and \
           node.children[0].type == token.STRING:
            insert_pos = idx + 1
            break

    for thing_after in root.children[insert_pos:]:
        if thing_after.type == token.NEWLINE:
            insert_pos += 1
            continue

        prefix = thing_after.prefix
        thing_after.prefix = u""
        break
    else:
        prefix = u""

    import_ = FromImport(u"__future__", [Leaf(token.NAME, feature, prefix=u" ")])

    children = [import_, Newline()]
    root.insert_child(insert_pos, Node(syms.simple_stmt, children, prefix=prefix))
コード例 #4
0
def future_import(feature, node):
    """
    This seems to work
    """
    root = find_root(node)

    if does_tree_import(u"__future__", feature, node):
        return

    for idx, node in enumerate(root.children):
        if node.type == syms.simple_stmt and \
           len(node.children) > 0 and node.children[0].type == token.STRING:
            # skip over docstring
            continue
        names = check_future_import(node)
        if not names:
            # not a future statement; need to insert before this
            break
        if feature in names:
            # already imported
            return

    import_ = FromImport(u'__future__', [Leaf(token.NAME, feature, prefix=" ")])
    children = [import_, Newline()]
    root.insert_child(idx, Node(syms.simple_stmt, children))
コード例 #5
0
def future_import(feature, node):
    """
    This seems to work
    """
    root = find_root(node)

    if does_tree_import(u"__future__", feature, node):
        return

    for idx, node in enumerate(root.children):
        if node.type == syms.simple_stmt and \
           len(node.children) > 0 and node.children[0].type == token.STRING:
            # skip over docstring
            continue
        names = check_future_import(node)
        if not names:
            # not a future statement; need to insert before this
            break
        if feature in names:
            # already imported
            return

    import_ = FromImport(u'__future__',
                         [Leaf(token.NAME, feature, prefix=" ")])
    children = [import_, Newline()]
    root.insert_child(idx, Node(syms.simple_stmt, children))
コード例 #6
0
def future_import2(feature, node):
    """
    An alternative to future_import() which might not work ...
    """
    root = find_root(node)

    if does_tree_import(u"__future__", feature, node):
        return

    insert_pos = 0
    for idx, node in enumerate(root.children):
        if node.type == syms.simple_stmt and node.children and \
           node.children[0].type == token.STRING:
            insert_pos = idx + 1
            break

    for thing_after in root.children[insert_pos:]:
        if thing_after.type == token.NEWLINE:
            insert_pos += 1
            continue

        prefix = thing_after.prefix
        thing_after.prefix = u""
        break
    else:
        prefix = u""

    import_ = FromImport(u"__future__",
                         [Leaf(token.NAME, feature, prefix=u" ")])

    children = [import_, Newline()]
    root.insert_child(insert_pos,
                      Node(syms.simple_stmt, children, prefix=prefix))
コード例 #7
0
    def transform(self, node, results):
        assert results

        # Not sure if this check is actually needed, and having it means
        # we can't remove these imports. Oh well.
        if not does_tree_import('__future__', 'print_function', node):
            return

        assert node.children[0] == Name(u"print")
        args = node.children[1:]
        if len(args) != 1:
            raise RuntimeError('I didn\'t expect this')
        args_node = args[0].clone()
        if args_node:
            if args_node.children[0] == Leaf(token.LPAR, '(') \
             and args_node.children[-1] == Leaf(token.RPAR, ')'):
                args_node.children[0].remove()
                args_node.children[-1].remove()
            args_node.prefix = u""

        log_call_args = args_node.children
        if len(log_call_args) == 1 and log_call_args[0].type == syms.arglist:
            log_call_args = log_call_args[0].children

        if any(node.type == syms.argument for node in log_call_args):
            raise RuntimeError(
                'Why are there kwargs in here!? How do we handle them? %s',
                log_call_args)

        return self._create_logging_call(log_call_args, node)
コード例 #8
0
    def add_globals(self, tree, inserted_types):
        """Add required globals to the tree. Idempotent."""
        # Copy imports if not already present
        top_lines = []

        def import_name(name, alias):
            return name + ('' if alias is None else ' as %s' % alias)

        for (pkg, pkg_alias), names in self._get_imports(inserted_types):
            if not names:
                if does_tree_import(None, pkg_alias or pkg, tree):
                    continue
                top_lines.append('import %s\n' % import_name(pkg, pkg_alias))
            else:
                assert pkg_alias is None
                import_names = []
                for name, alias in names:
                    if does_tree_import(pkg, alias or name, tree):
                        continue
                    import_names.append(import_name(name, alias))
                if not import_names:
                    continue
                top_lines.append('from %s import %s\n' %
                                 (pkg, ', '.join(import_names)))

        import_idx = [
            idx for idx, idx_node in enumerate(tree.children)
            if self.import_pattern.match(idx_node)
        ]
        if import_idx:
            insert_pos = import_idx[-1] + 1
        else:
            insert_pos = 0

            # first string (normally docstring)
            for idx, idx_node in enumerate(tree.children):
                if (idx_node.type == syms.simple_stmt and idx_node.children
                        and idx_node.children[0].type == token.STRING):
                    insert_pos = idx + 1
                    break

        if self.assignments:
            top_lines.append('\n')
            top_lines.extend(str(a).strip() + '\n' for a in self.assignments)
        top_lines = Util.parse_string(''.join(top_lines))
        for offset, offset_node in enumerate(top_lines.children[:-1]):
            tree.insert_child(insert_pos + offset, offset_node)
コード例 #9
0
 def type_updater(self, match, node):
     # type: (Match, Node) -> str
     # Replace `pkg.mod.SomeClass` with `SomeClass`
     # and remember to import it.
     word = match.group()
     if does_tree_import(None, word, node):
         # Check whether there already exists an import binding for this
         return word
     # If not, assume it's either builtin or from `typing`
     self.touch_typing_import(word, node)
     return word
コード例 #10
0
    def add_globals(self, node):
        """Add required globals to the root of node. Idempotent."""
        if self.added_pyi_globals:
            return
        # TODO: get rid of this -- added to prevent adding .parsed_pyi.top_lines every time
        # we annotate a different function in the same file, but can break when we run the tool
        # twice on the same file. Have to do something like what touch_import does.
        self.added_pyi_globals = True

        imports, top_lines = self.parsed_pyi.imports, self.parsed_pyi.top_lines

        # Copy imports if not already present
        for pkg, names in imports:
            if names is None:
                # TODO: do ourselves, touch_import puts stuff above license headers
                touch_import(None, pkg, node)  # == 'import pkg'
            else:
                for name in names:
                    touch_import(pkg, name, node)

        root = find_root(node)

        import_idx = [
            idx for idx, node in enumerate(root.children)
            if self.import_pattern.match(node)
        ]
        if import_idx:
            future_insert_pos = import_idx[0]
            top_insert_pos = import_idx[-1] + 1
        else:
            future_insert_pos = top_insert_pos = 0

            # first string (normally docstring)
            for idx, node in enumerate(root.children):
                if (node.type == syms.simple_stmt and node.children
                        and node.children[0].type == token.STRING):
                    future_insert_pos = top_insert_pos = idx + 1
                    break

        top_lines = '\n'.join(top_lines)
        top_lines = Util.parse_string(top_lines)  # strips some newlines
        for offset, node in enumerate(top_lines.children[:-1]):
            root.insert_child(top_insert_pos + offset, node)

        # touch_import doesn't do proper order for __future__
        pkg = '__future__'
        future_imports = [
            n for n in self.future_imports
            if not does_tree_import(pkg, n, root)
        ]
        for offset, name in enumerate(future_imports):
            node = FromImport(pkg, [Leaf(token.NAME, name, prefix=" ")])
            node = Node(syms.simple_stmt, [node, Newline()])
            root.insert_child(future_insert_pos + offset, node)
コード例 #11
0
def add_import(import_name, node):
    suite = get_parent_of_type(node, syms.suite)
    test_case = suite
    while test_case.parent.type != syms.file_input:
        test_case = test_case.parent
    file_input = test_case.parent

    if not does_tree_import(None, import_name, node):
        import_stmt = Node(syms.simple_stmt,
                           [Node(syms.import_name, [Name('import'), Name(import_name, prefix=' ')]),
                            Newline(),
                            ])
        insert_import(import_stmt, test_case, file_input)
コード例 #12
0
def add_import(import_name, node):
    suite = get_parent_of_type(node, syms.suite)
    test_case = suite
    while test_case.parent.type != syms.file_input:
        test_case = test_case.parent
    file_input = test_case.parent

    if not does_tree_import(None, import_name, node):
        import_stmt = Node(syms.simple_stmt, [
            Node(
                syms.import_name,
                [Name('import'), Name(import_name, prefix=' ')]),
            Newline(),
        ])
        insert_import(import_stmt, test_case, file_input)
コード例 #13
0
 def transform(self, node, results):
     from_import = results.get(u"from_import")
     from_import_submod = results.get(u"from_import_submod")
     name_import = results.get(u"name_import")
     dotted_name = results.get(u"dotted_name")
     name = results.get(u"name")
     names = results.get(u"names")
     attr = results.get(u"attr")
     imported = results.get(u"imported")
     if names:
         for name in names:
             if name.type == token.NAME:
                 self.fix_simple_name(name)
             elif name.type == syms.dotted_as_name:
                 self.fix_simple_name(name.children[0]) if name.children[0].type == token.NAME else \
                     self.fix_dotted_name(name.children[0])
             elif name.type == syms.dotted_name:
                 self.fix_dotted_name(name)
     elif from_import_submod:
         renamed = results.get(u"renamed")
         new_name, new_attr = self.get_dotted_import_replacement(
             name, attr, renamed=renamed)
         if new_attr is not None:
             name.replace(new_name)
             attr.replace(new_attr)
         else:
             children = [Name(u"import"), new_name]
             node.replace(
                 Node(syms.import_name, children, prefix=node.prefix))
     elif dotted_name:
         self.fix_dotted_name(dotted_name)
     elif name_import or from_import:
         self.fix_simple_name(name)
     elif name and not attr:
         if does_tree_import(None, MAPPING[name.value], node):
             self.fix_simple_name(name)
     elif name and attr:
         # Note that this will fix a dotted name that was never imported.
         # This will probably not matter.
         self.fix_dotted_name(node)
     elif imported and imported.type == syms.import_as_names:
         self.fix_submod_import(imported=imported.children,
                                node=node,
                                name=name.value)
コード例 #14
0
ファイル: fix_imports.py プロジェクト: vaddanak/challenges
 def transform(self, node, results):
     from_import = results.get("from_import")
     from_import_submod = results.get("from_import_submod")
     name_import = results.get("name_import")
     dotted_name = results.get("dotted_name")
     name = results.get("name")
     names = results.get("names")
     attr = results.get("attr")
     imported = results.get("imported")
     if names:
         for name in names:
             if name.type == token.NAME:
                 self.fix_simple_name(name)
             elif name.type == syms.dotted_as_name:
                 self.fix_simple_name(name.children[0]) if name.children[0].type == token.NAME else \
                 self.fix_dotted_name(name.children[0])
             elif name.type == syms.dotted_name:
                 self.fix_dotted_name(name)
     elif from_import_submod:
         renamed = results.get("renamed")
         new_name, new_attr = self.get_dotted_import_replacement(name, attr, renamed=renamed)
         if new_attr is not None:
             name.replace(new_name)
             attr.replace(new_attr)
         else:
             children = [Name("import"), new_name]
             node.replace(Node(syms.import_name, children, prefix=node.prefix))
     elif dotted_name:
         self.fix_dotted_name(dotted_name)
     elif name_import or from_import:
         self.fix_simple_name(name)
     elif name and not attr:
         if does_tree_import(None, MAPPING[name.value], node) and \
            is_probably_builtin(name):
             self.fix_simple_name(name)
     elif name and attr:
         # Note that this will fix a dotted name that was never imported.  This will probably not matter.
         self.fix_dotted_name(node)
     elif imported and imported.type == syms.import_as_names:
         self.fix_submod_import(imported=imported.children, node=node, name=name.value)
コード例 #15
0
def future_import(feature, node):
    """
    This seems to work
    """
    root = find_root(node)

    if does_tree_import(u"__future__", feature, node):
        return

    # Look for a shebang or encoding line
    shebang_encoding_idx = None

    for idx, node in enumerate(root.children):
        # Is it a shebang or encoding line?
        if is_shebang_comment(node) or is_encoding_comment(node):
            shebang_encoding_idx = idx
        if node.type == syms.simple_stmt and \
           len(node.children) > 0 and node.children[0].type == token.STRING:
            # skip over docstring
            continue
        names = check_future_import(node)
        if not names:
            # not a future statement; need to insert before this
            break
        if feature in names:
            # already imported
            return

    import_ = FromImport(u'__future__',
                         [Leaf(token.NAME, feature, prefix=" ")])
    if shebang_encoding_idx == 0 and idx == 0:
        # If this __future__ import would go on the first line,
        # detach the shebang / encoding prefix from the current first line.
        # and attach it to our new __future__ import node.
        import_.prefix = root.children[0].prefix
        root.children[0].prefix = u''
        # End the __future__ import line with a newline and add a blank line
        # afterwards:
    children = [import_, Newline()]
    root.insert_child(idx, Node(syms.simple_stmt, children))
コード例 #16
0
ファイル: fixer_util.py プロジェクト: BethMwangi/Flask-social
def future_import(feature, node):
    """
    This seems to work
    """
    root = find_root(node)

    if does_tree_import(u"__future__", feature, node):
        return

    # Look for a shebang or encoding line
    shebang_encoding_idx = None

    for idx, node in enumerate(root.children):
        # Is it a shebang or encoding line?
        if is_shebang_comment(node) or is_encoding_comment(node):
            shebang_encoding_idx = idx
        if node.type == syms.simple_stmt and \
           len(node.children) > 0 and node.children[0].type == token.STRING:
            # skip over docstring
            continue
        names = check_future_import(node)
        if not names:
            # not a future statement; need to insert before this
            break
        if feature in names:
            # already imported
            return

    import_ = FromImport(u'__future__', [Leaf(token.NAME, feature, prefix=" ")])
    if shebang_encoding_idx == 0 and idx == 0:
        # If this __future__ import would go on the first line,
        # detach the shebang / encoding prefix from the current first line.
        # and attach it to our new __future__ import node.
        import_.prefix = root.children[0].prefix
        root.children[0].prefix = u''
        # End the __future__ import line with a newline and add a blank line
        # afterwards:
    children = [import_ , Newline()]
    root.insert_child(idx, Node(syms.simple_stmt, children))
コード例 #17
0
def touch_import_top(package, name_to_import, node):
    """Works like `does_tree_import` but adds an import statement at the
    top if it was not imported (but below any __future__ imports) and below any
    comments such as shebang lines).

    Based on lib2to3.fixer_util.touch_import()

    Calling this multiple times adds the imports in reverse order.
        
    Also adds "standard_library.install_aliases()" after "from future import
    standard_library".  This should probably be factored into another function.
    """

    root = find_root(node)

    if does_tree_import(package, name_to_import, root):
        return

    # Ideally, we would look for whether futurize --all-imports has been run,
    # as indicated by the presence of ``from builtins import (ascii, ...,
    # zip)`` -- and, if it has, we wouldn't import the name again.

    # Look for __future__ imports and insert below them
    found = False
    for name in [
            'absolute_import', 'division', 'print_function', 'unicode_literals'
    ]:
        if does_tree_import('__future__', name, root):
            found = True
            break
    if found:
        # At least one __future__ import. We want to loop until we've seen them
        # all.
        start, end = None, None
        for idx, node in enumerate(root.children):
            if check_future_import(node):
                start = idx
                # Start looping
                idx2 = start
                while node:
                    node = node.next_sibling
                    idx2 += 1
                    if not check_future_import(node):
                        end = idx2
                        break
                break
        assert start is not None
        assert end is not None
        insert_pos = end
    else:
        # No __future__ imports.
        # We look for a docstring and insert the new node below that. If no docstring
        # exists, just insert the node at the top.
        for idx, node in enumerate(root.children):
            if node.type != syms.simple_stmt:
                break
            if not is_docstring(node):
                # This is the usual case.
                break
        insert_pos = idx

    if package is None:
        import_ = Node(syms.import_name, [
            Leaf(token.NAME, u"import"),
            Leaf(token.NAME, name_to_import, prefix=u" ")
        ])
    else:
        import_ = FromImport(package,
                             [Leaf(token.NAME, name_to_import, prefix=u" ")])
        if name_to_import == u'standard_library':
            # Add:
            #     standard_library.install_aliases()
            # after:
            #     from future import standard_library
            install_hooks = Node(syms.simple_stmt, [
                Node(syms.power, [
                    Leaf(token.NAME, u'standard_library'),
                    Node(syms.trailer, [
                        Leaf(token.DOT, u'.'),
                        Leaf(token.NAME, u'install_aliases')
                    ]),
                    Node(syms.trailer,
                         [Leaf(token.LPAR, u'('),
                          Leaf(token.RPAR, u')')])
                ])
            ])
            children_hooks = [install_hooks, Newline()]
        else:
            children_hooks = []

        # FromImport(package, [Leaf(token.NAME, name_to_import, prefix=u" ")])

    children_import = [import_, Newline()]
    old_prefix = root.children[insert_pos].prefix
    root.children[insert_pos].prefix = u''
    root.insert_child(
        insert_pos, Node(syms.simple_stmt, children_import, prefix=old_prefix))
    if len(children_hooks) > 0:
        root.insert_child(insert_pos + 1, Node(syms.simple_stmt,
                                               children_hooks))
コード例 #18
0
 def does_tree_import(self, package, name, string):
     node = parse(string)
     node = self._find_bind_rec('start', node)
     return fixer_util.does_tree_import(package, name, node)
コード例 #19
0
ファイル: fixer_util.py プロジェクト: CGTIC/Plone_SP
def touch_import_top(package, name_to_import, node):
    """Works like `does_tree_import` but adds an import statement at the
    top if it was not imported (but below any __future__ imports).

    Based on lib2to3.fixer_util.touch_import()

    Calling this multiple times adds the imports in reverse order.
        
    Also adds "standard_library.install_hooks()" after "from future import
    standard_library". This should probably be factored into another function.
    """

    root = find_root(node)

    if does_tree_import(package, name_to_import, root):
        return

    # Ideally, we would look for whether futurize --all-imports has been run,
    # as indicated by the presence of ``from future.builtins import (ascii, ...,
    # zip)`` -- and, if it has, we wouldn't import the name again.

    # Look for __future__ imports and insert below them
    found = False
    for name in ['absolute_import', 'division', 'print_function',
                 'unicode_literals']:
        if does_tree_import('__future__', name, root):
            found = True
            break
    if found:
        # At least one __future__ import. We want to loop until we've seen them
        # all.
        start, end = None, None
        for idx, node in enumerate(root.children):
            if check_future_import(node):
                start = idx
                # Start looping
                idx2 = start
                while node:
                    node = node.next_sibling
                    idx2 += 1
                    if not check_future_import(node):
                        end = idx2
                        break
                break
        assert start is not None
        assert end is not None
        insert_pos = end
    else:
        # No __future__ imports.
        # We look for a docstring and insert the new node below that. If no docstring
        # exists, just insert the node at the top.
        for idx, node in enumerate(root.children):
            if node.type != syms.simple_stmt:
                break
            if not (node.children and node.children[0].type == token.STRING):
                # This is the usual case.
                break
        insert_pos = idx

    if package is None:
        import_ = Node(syms.import_name, [
            Leaf(token.NAME, u"import"),
            Leaf(token.NAME, name_to_import, prefix=u" ")
        ])
    else:
        import_ = FromImport(package, [Leaf(token.NAME, name_to_import, prefix=u" ")])
        if name_to_import == u'standard_library':
            # Add:
            #     standard_library.install_hooks()
            # after:
            #     from future import standard_library
            install_hooks = Node(syms.simple_stmt,
                                 [Node(syms.power,
                                       [Leaf(token.NAME, u'standard_library'),
                                        Node(syms.trailer, [Leaf(token.DOT, u'.'),
                                        Leaf(token.NAME, u'install_hooks')]),
                                        Node(syms.trailer, [Leaf(token.LPAR, u'('),
                                                            Leaf(token.RPAR, u')')])
                                       ])
                                 ]
                                )
            children_hooks = [install_hooks, Newline()]
        else:
            children_hooks = []
        
        FromImport(package, [Leaf(token.NAME, name_to_import, prefix=u" ")])

    children_import = [import_, Newline()]
    root.insert_child(insert_pos, Node(syms.simple_stmt, children_import))
    if len(children_hooks) > 0:
        root.insert_child(insert_pos + 1, Node(syms.simple_stmt, children_hooks))
コード例 #20
0
    def transform(self, node, results):
        if does_tree_import('builtins', 'input', node):
            return

        return super(FixInput, self).transform(node, results)
コード例 #21
0
ファイル: test_util.py プロジェクト: pombreda/elm
 def does_tree_import(self, package, name, string):
     node = parse(string)
     # Find the binding of start -- that's what we'll go from
     node = self._find_bind_rec('start', node)
     return fixer_util.does_tree_import(package, name, node)
コード例 #22
0
ファイル: test_util.py プロジェクト: Rogerlin2013/CrossApp
 def does_tree_import(self, package, name, string):
     node = parse(string)
     # Find the binding of start -- that's what we'll go from
     node = self._find_bind_rec("start", node)
     return fixer_util.does_tree_import(package, name, node)