API reference

patchtree.config module

class patchtree.config.Config(context: type[Context] = <class 'patchtree.context.Context'>, target: type[Target] = <class 'patchtree.target.Target'>, argument_parser: type[ArgumentParser] = <class 'argparse.ArgumentParser'>, header: type[Header] = <class 'patchtree.header.Header'>, processors: dict[str, type[~patchtree.process.Process]]=<factory>, diff_context: int = 3, no_shebang: bool = False, default_patch_sources: list[Path] = <factory>, default_root: Path | None = None, patchspec_extensions: tuple[str, ...]=('.yaml', '.yml'))

Configuration dataclass.

This class contains all configuration options read from the configuration file.

argument_parser

ArgumentParser class type.

alias of ArgumentParser

context

Context class type.

alias of Context

default_patch_sources: list[Path]

List of default sources (empty by default).

default_root: Path | None = None

Default value of the -C/--root argument.

diff_context: int = 3

Lines of context to include in the diffs.

header

Header class type.

alias of Header

no_shebang: bool = False

Whether to suppress the shebang line with the git patch command to apply the patch.

patchspec_extensions: tuple[str, ...] = ('.yaml', '.yml')

File extensions removed for standalone patch specifications (see Writing patchset inputs).

processors: dict[str, type[Process]]

Maps processor IDs to Process class type (see Processors).

Note

If this member is defined in the configuration file, it is automatically merged with the default dict, with the configuration file keys taking priority.

target

Target class type.

alias of Target

patchtree.context module

class patchtree.context.Context(config: Config, options: Namespace)

Global app context / state holder.

apply(reverse: bool) None

Apply the patch in self.output and update the cache or reverse the patch in the cache.

collect_inputs(options: Namespace) list[Path]

Collect a list of patchset inputs depending on the globbing, patchset root and provided input path(s).

collect_targets(inputs: list[Path]) list[Target]

Create a list of targets and automatically resolve any patchspec naming conflicts.

This function creates a list of targets from the input paths, and ensures no standalone patchspecs or files referenced as inputs by any patchspecs are still treated as literal inputs.

Returns:

List of targets to process for final clean patch.

config: Config

Configuration class instance.

content: list[Target] = []

Patch targets (content).

create_target(input: Path, meta_inputs: list[Path] = []) Target

Create a target instance from an input path.

get_apply_cmd() list[str]

Create a command argument vector for applying the current patch.

Returns:

Command argument vector.

header: Header

Patch header instance.

in_place: bool

Whether to apply the changes directly to the target instead of outputting the .patch file.

inputs: list[Path] = []

A list of patchset inputs (relative to the current working directory).

is_empty: bool = False

Whether the output patch delta does not include any changes. Updated by make_patch.

log: Logger

Global log instance reference.

make_patch() str

Generate a clean patch using the header configuration and deltas from all targets.

Returns:

Clean patch contents

output: IO

Output IO stream used to write output patch to.

patchset_fs: FS

Target file system interface.

root: Path

Patchset root folder. All patchset input paths will be treated relative to this folder.

Note

The root member only changes the appearance of paths. All internal logic uses the “real” paths.

target_fs: FS

Target file system interface.

write() None

Write the clean patch to the selected output and close the output stream.

class patchtree.context.PatchspecLoader(context: Context, patch: File, input: Path)

YAML loader for patch specifications.

context: Context

Parent context.

input: Path

Path to file content.

input_specs: list[ProcessInputSpec] = []

List of inputs used by this patch specification.

parse() Target

Read the provided patch content and return a valid Target.

This method will raise an exception if the provided input is not a patchspec. This method also removes the patchspec YAML header from the input patch file’s content if a valid patchspec was read.

patch: File

File content to parse.

patchtree.diff module

class patchtree.diff.Diff(config: Config, file: str)

Produce a diff between two files. Either file may be absent, in which case extended header lines understood by git apply are generated.

a: File

Original (before) file.

b: File

Target (after) file.

compare() str

Generate delta in “git-diff-files -p” format (see https://git-scm.com/docs/diff-format#generate_patch_text_with_p).

file: str

Path to file relative to target dir.

class patchtree.diff.File(content: 'str | bytes | None' = None, mode: 'int' = 0)
content: str | bytes | None = None

The file’s contents, or None if it does not exist.

get_str() str

Get the file content as a string.

This function raises an Exception if the file is binary.

Returns:

  • An empty string if the file is empty.

  • The contents if the file is already open in text mode.

  • The system locale decoded representation of the file content.

is_binary() bool
Returns:

A boolean representing whether this file’s content is binary.

lines() list[str]

Get a list of lines in this file.

Returns:

  • A list of strings for each line in the file

  • An empty list if the file is empty or nonexistent

Note

This function only works for text files. Use is_binary to check this safely.

mode: int = 0

The file’s mode as returned by stat(3)’s stat.st_mode.

patchtree.fs module

class patchtree.fs.DiskFS(target)

Implementation of FS for a regular directory. Reads directly from the disk.

get_content(file)

Get the content of a file.

Returns:

  • The file content if it exists.

  • None if the file does not exist.

get_dir(dir)

List all items (i.e. file and directories) in a subdirectory.

Returns:

A list of all item names.

get_mode(file)

Get the mode of a file.

Returns:

  • The mode as returned by stat(3)’s stat.st_mode

  • 0 if the file does not exist

class patchtree.fs.FS(target: Path)

Filesystem interface.

get_content(file: Path) bytes | str | None

Get the content of a file.

Returns:

  • The file content if it exists.

  • None if the file does not exist.

get_dir(dir: Path) list[Path]

List all items (i.e. file and directories) in a subdirectory.

Returns:

A list of all item names.

get_file(spec: FileInputSpec) File

Get a File object with the content and mode of a file.

Returns:

A File object representing the content at spec

get_mode(file: Path) int

Get the mode of a file.

Returns:

  • The mode as returned by stat(3)’s stat.st_mode

  • 0 if the file does not exist

class patchtree.fs.ZipFS(target)

Implementation of FS for zip files. Reads directly from the archive.

dirs: set[Path] = {}

List of directories in this archive.

Some zip files may not include entries for all directories if they already define entries for files or subdirectories within. This set keeps all known directories.

files: dict[Path, ZipInfo] = {}

Map of path -> ZipInfo for all files in the archive.

get_content(file)

Get the content of a file.

Returns:

  • The file content if it exists.

  • None if the file does not exist.

get_dir(dir)

List all items (i.e. file and directories) in a subdirectory.

Returns:

A list of all item names.

get_info(path: Path) ZipInfo | None

Get the ZipInfo for a file in the archive

Returns:

  • The ZipInfo for the file at path

  • None if the file does not exist

get_mode(file)

Get the mode of a file.

Returns:

  • The mode as returned by stat(3)’s stat.st_mode

  • 0 if the file does not exist

zip: ZipFile

Underlying zip file.

patchtree.header module

class patchtree.header.Header(config: Config, context: Context)

Patch output header generator.

The header is formatted as

  1. shebang

  2. patchtree version info

  3. extra version info (empty by default)

  4. license (empty by default)

license = None

License text (optional).

name = 'patchtree'

Program name shown in version info.

write_license() str

Write a license if it is defined.

write_shebang() str

Write a shebang line to apply the output patch unless the --no-shebang option was passed.

write_version() str

Write the patchtree name and version number.

write_version_extra() str

Write extra version information (empty).

This method is meant to be implemented by subclasses of Header defined in the configuration file.

patchtree.process module

class patchtree.process.CoccinelleProcess(target, data)

Coccinelle transformer.

transform()

Perform the transformation of this processor.

Returns:

Processed file.

class patchtree.process.ExecProcess(target, data)

Executable transformer.

transform()

Perform the transformation of this processor.

Returns:

Processed file.

class patchtree.process.Jinja2Process(target: Target, data: dict[Hashable, Any] = {})

Jinja2 preprocessor.

get_template_vars() dict[str, Any]

Generate template variables.

This method returns an empty dict by default and is meant to be implemented by the user by creating a subclass and registering it through the configuration file.

Returns:

A dict of variables defined in the template.

transform()

Perform the transformation of this processor.

Returns:

Processed file.

class patchtree.process.MergeProcess(target, data)

Merge transformer.

transform()

Perform the transformation of this processor.

Returns:

Processed file.

class patchtree.process.Process(target: Target, data: dict[Hashable, Any] = {})

Process base interface.

input_spec: ProcessInputSpec

Processor input option (see Processors)

target: Target

Patch file context.

target_spec: ProcessInputSpec

Processor target option (optionally used, see Processors)

transform() File

Perform the transformation of this processor.

Returns:

Processed file.

class patchtree.process.TouchProcess(target, data)

Touch transformer.

transform()

Perform the transformation of this processor.

Returns:

Processed file.

patchtree.spec module

class patchtree.spec.DefaultInputSpec

Spec to use the output of the previous processor as input (concrete)

class patchtree.spec.FileInputSpec(path: Path)

Processor input referencing a filename (abstract)

class patchtree.spec.LiteralInputSpec(content: str)

Spec to use a literal string as input (concrete)

class patchtree.spec.PatchsetFileInputSpec(path: Path)

Spec to use a file (referenced by name) in the patchset directory (concrete)

class patchtree.spec.ProcessInputSpec

Processor input specification (abstract base)

class patchtree.spec.TargetFileInputSpec(path: Path)

Spec to use a file (referenced by name) in the target directory (concrete)

patchtree.target module

class patchtree.target.Target(context: Context, file: Path, data: dict[Hashable, Any] = {})

A single patched file, including its processors.

file: str

The name of the patched file in the target.

get_file(spec: ProcessInputSpec) File

Get the file contents from a ProcessInputSpec (called by Processor).

write() str

Apply all processors, compare to the target and return the delta.