Search code examples
pythonlibcst

Apply libcst codemod and skip test files


I am writing a codemod with libcst which inherits from VisitorBasedCodemodCommand. It works fine but is rather slow. One simple trick would be to skip all test files which start with test_ by convention. However I haven't been able to find a place to add such logic in my codemod.

I saw a SkipFile exception but I don't know from where I could trigger it.

How can I ignore my test files?


Solution

  • You can raise SkipFile anywhere in the codemod when you detect that the current file can not be modified by the codemod. Since you know upfront you want to skip the test files completely, you can bail out on module node visit already, for example:

    import pathlib
    import libcst as cst
    from libcst.codemod import VisitorBasedCodemodCommand, SkipFile
    
    
    class SkipTests(VisitorBasedCodemodCommand):
        def visit_Module(self, mod: cst.Module) -> bool | None:
            if pathlib.Path(self.context.filename).name.startswith("test_"):
                raise SkipFile("not touching any tests")
            return True
    

    Now, when you invoke libcst.tool with the codemod, you should see a log line for each skipped file:

    $ python -m libcst.tool codemod so.SkipTests .
    Calculating full-repo metadata...
    Executing codemod...
    Codemodding /path/to/example/test_mod.py
    Skipped codemodding /path/to/example/test_mod.py: not touching any tests
    
    Finished codemodding 8 files!
     - Transformed 7 files successfully.
     - Skipped 1 files.
     - Failed to codemod 0 files.
     - 0 warnings were generated.