Source code for ralph.recovery.failure_details

"""Shared helpers for extracting and matching rich failure details."""

from __future__ import annotations

from typing import TYPE_CHECKING, cast

if TYPE_CHECKING:
    from collections.abc import Iterable


[docs] def failure_detail_parts(exc: BaseException | str) -> list[str]: """Return all textual detail surfaces associated with a failure.""" if isinstance(exc, str): text = exc.strip() return [text] if text else [] parts: list[str] = [] message = str(exc).strip() if message: parts.append(message) stderr = cast("object", getattr(exc, "stderr", None)) if isinstance(stderr, str): stderr_text = stderr.strip() if stderr_text and stderr_text not in parts: parts.append(stderr_text) parsed_output = cast("object", getattr(exc, "parsed_output", None)) if isinstance(parsed_output, list): for item in parsed_output: item_text = str(item).strip() if item_text: parts.append(item_text) return parts
[docs] def contains_casefolded_marker(parts: Iterable[str], markers: Iterable[str]) -> bool: """Return True when any marker appears in any part, case-insensitively.""" folded_markers = tuple(marker.casefold() for marker in markers) for part in parts: folded_part = part.casefold() if any(marker in folded_part for marker in folded_markers): return True return False
[docs] def has_stale_session_details( exc: BaseException | str, markers: Iterable[str], ) -> bool: """Return True when any failure surface carries a stale-session signal.""" return contains_casefolded_marker(failure_detail_parts(exc), markers)
__all__ = [ "contains_casefolded_marker", "failure_detail_parts", "has_stale_session_details", ]