Skip to content

Latest commit

 

History

History
163 lines (128 loc) · 7.9 KB

codemods.rst

File metadata and controls

163 lines (128 loc) · 7.9 KB

Codemods

LibCST defines a codemod as an automated refactor that can be applied to a codebase of arbitrary size. Codemods are provided as a framework for writing higher-order transforms that consist of other, simpler transforms. It includes provisions for quickly creating a command-line interface to execute a codemod.

Codemod Base

All codemods derive from a common base, :class:`~libcst.codemod.Codemod`. This class includes a context, automatic metadata resolution and multi-pass transform support. Codemods are intended to be executed using the :func:`~libcst.codemod.transform_module` interface.

.. autoclass:: libcst.codemod.Codemod
.. autoclass:: libcst.codemod.CodemodContext

As a convenience, LibCST-compatible visitors are provided which extend the feature-set of :class:`~libcst.codemod.Codemod` to LibCST visitors and transforms. Remember that :class:`~libcst.codemod.ContextAwareTransformer` is still a :class:`~libcst.codemod.Codemod`, so you should still execute it using :func:`~libcst.codemod.transform_module`.

.. autoclass:: libcst.codemod.ContextAwareTransformer
  :exclude-members: transform_module_impl
.. autoclass:: libcst.codemod.ContextAwareVisitor

It is often necessary to bail out of a codemod mid-operation when you realize that you do not want to operate on a module. This can be for any reason such as realizing the module includes some operation that you do not support. If you wish to skip a module, you can raise the :class:`~libcst.codemod.SkipFile` exception. For codemods executed using the :func:`~libcst.codemod.transform_module` interface, all warnings emitted up to the exception being thrown will be preserved in the result.

.. autoclass:: libcst.codemod.SkipFile

Finally, its often easier to test codemods by writing verification tests instead of running repeatedly on your project. LibCST makes this easy with :class:`~libcst.codemod.CodemodTest`. Often you can develop the majority of your codemod using just tests, augmenting functionality when you run into an unexpected edge case when running it against your repository.

.. autoclass:: libcst.codemod.CodemodTest
  :inherited-members:
  :exclude-members: addCleanup, addTypeEqualityFunc, assertAlmostEqual, assertAlmostEquals, assertCountEqual, assertDictContainsSubset, assertDictEqual, assertEqual, assertEquals, assertFalse, assertGreater, assertGreaterEqual, assertIn, assertIs, assertIsInstance, assertIsNone, assertIsNot, assertIsNotNone, assertLess, assertLessEqual, assertListEqual, assertLogs, assertMultiLineEqual, assertNotAlmostEqual, assertNotAlmostEquals, assertNotEqual, assertNotEquals, assertNotIn, assertNotIsInstance, assertNotRegex, assertNotRegexpMatches, assertRaises, assertRaisesRegex, assertRaisesRegexp, assertRegex, assertRegexpMatches, assertSequenceEqual, assertSetEqual, assertTrue, assertTupleEqual, assertWarns, assertWarnsRegex, assert_, countTestCases, debug, defaultTestResult, doCleanups, fail, failIf, failIfAlmostEqual, failIfEqual, failUnless, failUnlessAlmostEqual, failUnlessEqual, failUnlessRaises, failureException, id, longMessage, maxDiff, run, setUp, classmethod, setUpClass, shortDescription, skipTest, subTest, tearDown, tearDownClass

Execution Interface

As documented in the Codemod Base section above, codemods are meant to be programmatically executed using :func:`~libcst.codemod.transform_module`. Executing in this manner handles all of the featureset of codemods, including metadata calculation and exception handling.

.. autofunction:: libcst.codemod.transform_module
.. autoclass:: libcst.codemod.TransformResult
.. autoclass:: libcst.codemod.TransformSuccess
.. autoclass:: libcst.codemod.TransformFailure
.. autoclass:: libcst.codemod.TransformSkip
.. autoclass:: libcst.codemod.SkipReason
.. autoclass:: libcst.codemod.TransformExit

Command-Line Support

LibCST includes additional support to facilitate faster development of codemods which are to be run at the command-line. This is achieved through the :class:`~libcst.codemod.CodemodCommand` class and the codemod utility which lives inside libcst.tool. The :class:`~libcst.codemod.CodemodCommand` class provides a codemod description and an interface to add arguments to the command-line. This is translated to a custom help message and command-line options that a user can provide when running a codemod at the command-line.

For a brief overview of supported universal options, run the codemod utility like so:

python3 -m libcst.tool codemod --help

The utility provides support for gathering up and parallelizing codemods across a series of files or directories, auto-formatting changed code according to a configured formatter, generating a unified diff of changes instead of applying them to files, taking code from stdin and codemodding it before returning to stdout, and printing progress and warnings to stderr during execution of a codemod.

Help is auto-customized if a codemod class is provided, including any added options and the codemod description. For an example, run the codemod utility like so:

python3 -m libcst.tool codemod noop.NOOPCommand --help

A second utility, list, can list all available codemods given your configuration. Run it like so:

python3 -m libcst.tool list

Finally, to set up a directory for codemodding using these tools, including additional directories where codemods can be found, use the initialize utility. To see help for how to use this, run the initialize utility like so:

python3 -m libcst.tool initialize --help

The above tools operate against any codemod which subclasses from :class:`~libcst.codemod.CodemodCommand`. Remember that :class:`~libcst.codemod.CodemodCommand` is a subclass of :class:`~libcst.codemod.Codemod`, so all of the features documented in the :ref:`libcst-codemod-base` section are available in addition to command-line support. Any command-line enabled codemod can also be programmatically instantiated and invoked using the above-documented :func:`~libcst.codemod.transform_module` interface.

.. autoclass:: libcst.codemod.CodemodCommand
  :exclude-members: transform_module

Additionally, a few convenience classes have been provided which take the boilerplate out of common types of codemods:

.. autoclass:: libcst.codemod.VisitorBasedCodemodCommand
.. autoclass:: libcst.codemod.MagicArgsCodemodCommand
  :exclude-members: transform_module_impl

Command-Line Toolkit

Several helpers for constructing a command-line interface are provided. These are used in the codemod utility to provide LibCST's de-facto command-line interface but they are also available to be used directly in the case that circumstances demand a custom command-line tool.

.. autofunction:: libcst.codemod.gather_files
.. autofunction:: libcst.codemod.exec_transform_with_prettyprint
.. autofunction:: libcst.codemod.parallel_exec_transform_with_prettyprint
.. autoclass:: libcst.codemod.ParallelTransformResult
.. autofunction:: libcst.codemod.diff_code

Library of Transforms

LibCST additionally includes a library of transforms to reduce the need for boilerplate inside codemods. As of now, the list includes the following helpers.

.. autoclass:: libcst.codemod.visitors.GatherImportsVisitor
  :no-undoc-members:
.. autoclass:: libcst.codemod.visitors.GatherExportsVisitor
  :no-undoc-members:
.. autoclass:: libcst.codemod.visitors.AddImportsVisitor
  :no-undoc-members:
.. autoclass:: libcst.codemod.visitors.RemoveImportsVisitor
  :no-undoc-members:
.. autoclass:: libcst.codemod.visitors.ApplyTypeAnnotationsVisitor
  :no-undoc-members:
.. autoclass:: libcst.codemod.visitors.GatherUnusedImportsVisitor
  :no-undoc-members:
.. autoclass:: libcst.codemod.visitors.GatherCommentsVisitor
  :no-undoc-members:
.. autoclass:: libcst.codemod.visitors.GatherNamesFromStringAnnotationsVisitor
  :no-undoc-members: