Skip to content

system

ruff_sync.system

System and subprocess utilities for ruff-sync.

LOGGER module-attribute

LOGGER = getLogger(__name__)

get_ruff_rule_markdown async

get_ruff_rule_markdown(rule_code)

Execute ruff rule <CODE> and return the Markdown documentation.

Parameters:

Name Type Description Default
rule_code str

The Ruff rule code (e.g., 'RUF012').

required

Returns:

Type Description
str | None

The Markdown documentation for the rule, or None if the execution fails

str | None

or the rule is not found.

Source code in src/ruff_sync/system.py
async def get_ruff_rule_markdown(rule_code: str) -> str | None:
    """Execute `ruff rule <CODE>` and return the Markdown documentation.

    Args:
        rule_code: The Ruff rule code (e.g., 'RUF012').

    Returns:
        The Markdown documentation for the rule, or None if the execution fails
        or the rule is not found.
    """
    cmd: Final[list[str]] = ["ruff", "rule", rule_code]
    return await _run_ruff_command(cmd, f"ruff rule {rule_code}")

get_ruff_config_markdown async

get_ruff_config_markdown(setting_path)

Execute ruff config <SETTING> and return the Markdown documentation.

Parameters:

Name Type Description Default
setting_path str

The Ruff configuration setting path (e.g., 'lint.select').

required

Returns:

Type Description
str | None

The Markdown documentation for the setting, or None if the execution fails.

Source code in src/ruff_sync/system.py
async def get_ruff_config_markdown(setting_path: str) -> str | None:
    """Execute `ruff config <SETTING>` and return the Markdown documentation.

    Args:
        setting_path: The Ruff configuration setting path (e.g., 'lint.select').

    Returns:
        The Markdown documentation for the setting, or None if the execution fails.
    """
    # Strip 'tool.ruff.' prefix if present as 'ruff config' expects relative paths
    clean_path = setting_path.removeprefix("tool.ruff.")
    if not clean_path or clean_path == "tool.ruff":
        return None
    cmd: Final[list[str]] = ["ruff", "config", clean_path]
    return await _run_ruff_command(cmd, f"ruff config {clean_path}")

get_all_ruff_rules async

get_all_ruff_rules()

Execute ruff rule --all --output-format json and return the parsed rules.

Returns:

Type Description
list[RuffRule]

A list of dictionaries representing all supported Ruff rules.

Source code in src/ruff_sync/system.py
async def get_all_ruff_rules() -> list[RuffRule]:
    """Execute `ruff rule --all --output-format json` and return the parsed rules.

    Returns:
        A list of dictionaries representing all supported Ruff rules.
    """
    cmd: Final[list[str]] = ["ruff", "rule", "--all", "--output-format", "json"]
    output = await _run_ruff_command(cmd, "ruff rule --all")
    if not output:
        return []
    try:
        data = json.loads(output)
    except json.JSONDecodeError:
        LOGGER.exception("Failed to parse Ruff rules JSON.")
        return []

    if isinstance(data, list):
        return data
    return []

get_ruff_linters async

get_ruff_linters()

Execute ruff linter --output-format json and return the parsed linters.

Returns:

Type Description
list[RuffLinter]

A list of dictionaries representing Ruff linter categories.

Source code in src/ruff_sync/system.py
async def get_ruff_linters() -> list[RuffLinter]:
    """Execute `ruff linter --output-format json` and return the parsed linters.

    Returns:
        A list of dictionaries representing Ruff linter categories.
    """
    cmd: Final[list[str]] = ["ruff", "linter", "--output-format", "json"]
    output = await _run_ruff_command(cmd, "ruff linter")
    if not output:
        return []
    try:
        data = json.loads(output)
    except json.JSONDecodeError:
        LOGGER.exception("Failed to parse Ruff linters JSON.")
        return []

    if isinstance(data, list):
        return data
    return []

compute_effective_rules

compute_effective_rules(all_rules, toml_config)

Determine the status (Enabled, Ignored, Disabled) for each rule.

Parameters:

Name Type Description Default
all_rules list[RuffRule]

The list of all supported rules.

required
toml_config Mapping[str, Any]

The local configuration dictionary.

required

Returns:

Type Description
list[RuffRule]

The list of rules enriched with a 'status' key.

Source code in src/ruff_sync/system.py
def compute_effective_rules(
    all_rules: list[RuffRule], toml_config: Mapping[str, Any]
) -> list[RuffRule]:
    """Determine the status (Enabled, Ignored, Disabled) for each rule.

    Args:
        all_rules: The list of all supported rules.
        toml_config: The local configuration dictionary.

    Returns:
        The list of rules enriched with a 'status' key.
    """
    # The config may be "wrapped" (top-level 'tool' key) or
    # "unwrapped" (direct Ruff config as returned by load_local_ruff_config).
    lint = toml_config.get("lint")
    if lint is None:
        lint = toml_config.get("tool", {}).get("ruff", {}).get("lint", {})

    select = set(lint.get("select", [])) | set(lint.get("extend-select", []))
    ignore = set(lint.get("ignore", [])) | set(lint.get("extend-ignore", []))

    # If no select/extend-select is provided, Ruff defaults to E and F
    if not lint.get("select") and not lint.get("extend-select"):
        select.update(["E", "F"])

    enriched: list[RuffRule] = []
    for rule in all_rules:
        code = rule["code"]

        # Find longest matching select prefix
        best_select_len = -1
        for s in select:
            if code.startswith(s):
                best_select_len = max(best_select_len, len(s))

        # Find longest matching ignore prefix
        best_ignore_len = -1
        for i in ignore:
            if code.startswith(i):
                best_ignore_len = max(best_ignore_len, len(i))

        status = "Disabled"
        if best_select_len > best_ignore_len:
            status = "Enabled"
        elif best_ignore_len >= best_select_len and best_ignore_len != -1:
            status = "Ignored"

        rule_with_status = dict(rule)
        rule_with_status["status"] = status
        enriched.append(rule_with_status)  # type: ignore[arg-type]

    return enriched