Ejemplo n.º 1
0
    def remove_unused_import_by_node(context: CodemodContext,
                                     node: cst.CSTNode) -> None:
        """
        Schedule any imports referenced by ``node`` or one of its children
        to be removed in a future invocation of this class by updating the
        ``context`` to include the ``module``, ``obj`` and ``alias`` for each
        import in question. When subclassing from
        :class:`~libcst.codemod.CodemodCommand`, this will be performed for you
        after your transform finishes executing. If you are subclassing from a
        :class:`~libcst.codemod.Codemod` instead, you will need to call the
        :meth:`~libcst.codemod.Codemod.transform_module` method on the module
        under modification with an instance of this class after performing your
        transform. Note that all imports that are referenced by this ``node``
        or its children will only be removed if they are not in use at the time
        of exeucting :meth:`~libcst.codemod.Codemod.transform_module`
        on an instance of :class:`~libcst.codemod.visitors.AddImportsVisitor`
        in order to avoid removing an in-use import.
        """

        # Special case both Import and ImportFrom so they can be
        # directly removed here.
        if isinstance(node, cst.Import):
            for import_alias in node.names:
                RemoveImportsVisitor.remove_unused_import(
                    context,
                    import_alias.evaluated_name,
                    asname=import_alias.evaluated_alias,
                )
        elif isinstance(node, cst.ImportFrom):
            names = node.names
            if isinstance(names, cst.ImportStar):
                # We don't handle removing this, so ignore it.
                return
            module_name = get_absolute_module_for_import(
                context.full_module_name, node)
            if module_name is None:
                raise Exception(
                    "Cannot look up absolute module from relative import!")
            for import_alias in names:
                RemoveImportsVisitor.remove_unused_import(
                    context,
                    module_name,
                    obj=import_alias.evaluated_name,
                    asname=import_alias.evaluated_alias,
                )
        else:
            # Look up all children that could have been imported. Any that
            # we find will be scheduled for removal.
            node.visit(RemovedNodeVisitor(context))
Ejemplo n.º 2
0
    def rewrite(self, tree: cst.CSTNode, env: SymbolTable,
                metadata: tp.MutableMapping) -> PASS_ARGS_T:
        if self.replace_and:
            visitor = AndTransformer()
            tree = tree.visit(visitor)

        if self.replace_or:
            visitor = OrTransformer()
            tree = tree.visit(visitor)

        if self.replace_not:
            visitor = NotTransformer()
            tree = tree.visit(visitor)

        return tree, env, metadata
Ejemplo n.º 3
0
 def __assert_visit_returns_identity(self, node: cst.CSTNode) -> None:
     """
     When visit is called with a visitor that acts as a no-op, the visit method
     should return the same node it started with.
     """
     # TODO: We're only checking equality right now, because visit currently clones
     # the node, since that was easier to implement. We should fix that behavior in a
     # later version and tighten this check.
     self.assertEqual(node, node.visit(_NOOPVisitor()))
Ejemplo n.º 4
0
def _replace_names(
    node: libcst.CSTNode,
    wrapper: libcst.metadata.MetadataWrapper,
    replacements: Dict[str, libcst.CSTNode],
) -> libcst.CSTNode:
    replacer = _ReplaceTransformer(replacements)
    with replacer.resolve(wrapper):
        # The result of node.visit can never be a RemovalSentinel.
        return cast(libcst.CSTNode, node.visit(replacer))
Ejemplo n.º 5
0
    def rewrite(self,
            tree: cst.CSTNode,
            env: SymbolTable,
            metadata: tp.MutableMapping) -> PASS_ARGS_T:

        if not isinstance(self.phi, str):
            phi_name = gen_free_name(tree, env, self.phi_name_prefix)
            env.locals[phi_name] = self.phi
        else:
            phi_name = self.phi

        visitor = IfExpTransformer(phi_name)
        tree = tree.visit(visitor)
        return tree, env, metadata
Ejemplo n.º 6
0
def assert_(py_ast: cst.CSTNode, transform: Transform) -> cst.CSTNode:
    """
    TODO: in programming `assert` has a context of being passive, not fixing if it finds that it's incorrect,
    perhaps a more active word should be chosen. Maybe *ensure*?
    """
    matches = transform.matches

    first_ref_index = None
    find_attempt = tryFirst(transform.capture_reference_indices)
    if find_attempt is not notFound:
        _, (first_ref_index, _) = first(transform.capture_reference_indices)

    @ unified_visit
    class Transformer(cst.CSTTransformer):
        def _leave(self, original: cst.CSTNode, updated: cst.CSTNode) -> cst.CSTNode:
            # TODO: if global scope query create a module tree from scratch?
            # NOTE: in the future can cache lib cst node comparisons for speed
            match = notFound
            if first_ref_index is not None:
                match = tryFind(lambda m: original.deep_equals(
                    m.path[first_ref_index].node), matches)
            if match is not notFound:
                from_assert = first(astNodeFromAssertion(transform, match))
                return from_assert
            elif original in transform.references:
                # TODO: replace references to anything destroyed by the transform
                pass
            elif find_attempt is notFound and isinstance(updated, cst.Module):
                module_match = Match(
                    [CaptureExpr().contextualize(node=updated)])
                return updated.with_changes(body=(*updated.body, *astNodeFromAssertion(transform, module_match)))
            else:
                return updated

    transformed_tree = py_ast.visit(Transformer())

    return transformed_tree
Ejemplo n.º 7
0
def unmangle_nodes(
    tree: cst.CSTNode,
    template_replacements: Mapping[str, ValidReplacementType],
) -> cst.CSTNode:
    unmangler = TemplateTransformer(template_replacements)
    return ensure_type(tree.visit(unmangler), cst.CSTNode)
Ejemplo n.º 8
0
def unroll_for_loops(tree: cst.CSTNode,
                     env: tp.Mapping[str, tp.Any]) -> cst.CSTNode:
    return tree.visit(Unroller(env))
Ejemplo n.º 9
0
    def rewrite(self, tree: cst.CSTNode, env: SymbolTable,
                metadata: tp.MutableMapping) -> PASS_ARGS_T:

        visitor = AssertRemover()
        tree = tree.visit(visitor)
        return tree, env, metadata
Ejemplo n.º 10
0
def _normalize(node: cst.CSTNode):
    node = node.visit(StripParens())
    node = node.visit(WhiteSpaceNormalizer())
    node.validate_types_deep()
    return node