mafw.devtools.toolchain.precommit_modifier

Pre-commit configuration modifier for toolchain management.

This module provides the PreCommitModifier helper that reads, modifies, and writes .pre-commit-config.yaml files while preserving YAML comments, key ordering, and inline formatting. It is used by concrete ToolChainTool implementations (e.g. Ruff) to keep pre-commit hook revisions in sync with pyproject.toml.

The implementation uses a hybrid approach: ruamel.yaml in round-trip mode (typ='rt') for parsing and validating the YAML structure, combined with string-level replacement for the actual rev field update. This guarantees that all bytes not related to the targeted rev value remain unchanged after a write operation.

Classes

PreCommitModifier()

Read, modify, and write .pre-commit-config.yaml preserving formatting.

class mafw.devtools.toolchain.precommit_modifier.PreCommitModifier[source]

Bases: object

Read, modify, and write .pre-commit-config.yaml preserving formatting.

This class uses a hybrid approach: ruamel.yaml in round-trip mode for parsing and locating repository entries, and string-level replacement for the actual rev field update. This guarantees that all bytes not related to the updated rev value remain byte-for-byte identical — including sequence indentation, comments, and inline formatting that ruamel.yaml might otherwise normalize.

Typical usage:

modifier = PreCommitModifier()
modifier.read(Path('.pre-commit-config.yaml'))
modifier.update_rev(
    repo_url='https://github.com/astral-sh/ruff-pre-commit',
    new_rev='v0.15.12',
)
modifier.write(Path('.pre-commit-config.yaml'))
read(path: Path) None[source]

Load a .pre-commit-config.yaml file into memory.

Parameters:

path (Path) – Path to the .pre-commit-config.yaml file.

Raises:

DevtoolsError – If the file does not exist, cannot be read, or contains invalid YAML.

update_rev(repo_url: str, new_rev: str) None[source]

Update the rev field for a repository entry matching the given URL.

Locates the repository entry whose repo field matches repo_url and replaces its rev value with new_rev. The replacement is performed at the string level to guarantee byte-for-byte preservation of all other content.

Parameters:
  • repo_url (str) – The repository URL to search for in the repos list.

  • new_rev (str) – The new revision string to set (e.g. "v0.15.12"). Must be non-empty and at most 128 characters.

Raises:

DevtoolsError – If no data has been loaded, if the URL is not found, if the matched entry has no rev field, or if new_rev is empty or exceeds 128 characters.

write(path: Path) None[source]

Write the (possibly modified) configuration back to disk.

The output preserves all YAML comments, key ordering, and inline formatting from the original file. Only explicitly modified fields (via update_rev()) will differ from the original content.

Parameters:

path (Path) – Path where the configuration should be written.

Raises:

DevtoolsError – If no data has been loaded or if writing fails.

mafw.devtools.toolchain.precommit_modifier._extract_raw_rev(content: str, repo_url: str) str[source]

Extract the literal rev value from raw YAML content for a given repo URL.

This avoids relying on ruamel.yaml’s parsed representation, which may coerce values (e.g. 0000000 becomes integer 0 under YAML 1.1 octal rules). Instead, we locate the rev: line following the repo URL and extract the value as a raw string.

Parameters:
  • content – The raw YAML file content.

  • repo_url – The repository URL whose rev to extract.

Returns:

The literal rev value as it appears in the file.

Raises:

DevtoolsError – If the rev line cannot be found.

mafw.devtools.toolchain.precommit_modifier._replace_rev_after_repo(content: str, repo_url: str, old_rev: str, new_rev: str) str[source]

Replace the rev value in raw YAML content after a specific repo URL line.

This function finds the line containing the repo URL and then locates the first rev: line that follows it (before the next - repo: line or end of repos). It replaces only the old_rev value on that line.

Parameters:
  • content – The raw YAML file content.

  • repo_url – The repository URL to locate.

  • old_rev – The current rev value to replace.

  • new_rev – The new rev value to set.

Returns:

The modified content with only the rev value changed.

mafw.devtools.toolchain.precommit_modifier._MAX_REV_LENGTH: Final[int] = 128

Maximum allowed length for a rev string value.