Experimental APIs

These APIs may change at any time (including in minor releases) with no notice. You probably shouldn’t use them, but if you do, you should pin your application to an exact release of LibCST to avoid breakages.

Reentrant Code Generation

class libcst.metadata.ExperimentalReentrantCodegenProvider[source]

An experimental API that allows fast generation of modified code by recording an initial code-generation pass, and incrementally applying updates. It is a performance optimization for a few niche use-cases and is not user-friendly.

This API may change at any time without warning (including in minor releases).

This is rarely useful. Instead you should make multiple modifications to a single syntax tree, and generate the code once. However, we can think of a few use-cases for this API (hence, why it exists):

  • When linting a file, you might generate multiple independent patches that a user can accept or reject. Depending on your architecture, it may be advantageous to avoid regenerating the file when computing each patch.

  • You might want to call out to an external utility (e.g. a typechecker, such as pyre or mypy) to validate a small change. You may need to generate and test lots of these patches.

Restrictions:

  • For safety and sanity reasons, the smallest/only level of granularity is a statement. If you need to patch part of a statement, you regenerate the entire statement. If you need to regenerate an entire module, just call libcst.Module.code().

  • This does not (currently) operate recursively. You can patch an unpatched piece of code multiple times, but you can’t layer additional patches on an already patched piece of code.

class libcst.metadata.CodegenPartial[source]

Provided by ExperimentalReentrantCodegenProvider.

Stores enough information to generate either a small patch (get_modified_code_range()) or a new file (get_modified_code()) by replacing the old node at this position.

start_offset
end_offset
has_trailing_newline
get_original_module_code() → str[source]

Equivalent to libcst.Module.bytes() on the top-level module that contains this statement, except that it uses the cached result from our previous code generation pass, so it’s faster.

get_original_module_bytes() → bytes[source]

Equivalent to libcst.Module.bytes() on the top-level module that contains this statement, except that it uses the cached result from our previous code generation pass, so it’s faster.

get_original_statement_code() → str[source]

Equivalent to libcst.Module.code_for_node() on the current statement, except that it uses the cached result from our previous code generation pass, so it’s faster.

get_modified_statement_code(node: libcst._nodes.statement.BaseStatement) → str[source]

Gets the new code for node as if it were in same location as the old statement being replaced. This means that it inherits details like the old statement’s indentation.

get_modified_module_code(node: libcst._nodes.statement.BaseStatement) → str[source]

Gets the new code for the module at the root of this statement’s tree, but with the supplied replacement node in its place.

get_modified_module_bytes(node: libcst._nodes.statement.BaseStatement) → bytes[source]

Gets the new bytes for the module at the root of this statement’s tree, but with the supplied replacement node in its place.