Python · 2104 bytes Raw Blame History
1 """Exception hierarchy for dlm-sway.
2
3 Every error sway raises inherits from :class:`SwayError` so callers can
4 catch the whole family with a single ``except``. Subclasses carry enough
5 context (spec paths, probe names, missing extras) for the CLI to render
6 actionable messages without the caller having to introspect an exception
7 chain.
8 """
9
10 from __future__ import annotations
11
12
13 class SwayError(Exception):
14 """Root of the dlm-sway exception hierarchy."""
15
16
17 class SpecValidationError(SwayError):
18 """A ``sway.yaml`` (or equivalent) failed pydantic validation.
19
20 Parameters
21 ----------
22 message:
23 Human-readable summary of what went wrong.
24 source:
25 Path or identifier of the spec being validated, if known.
26 """
27
28 def __init__(self, message: str, *, source: str | None = None) -> None:
29 super().__init__(message)
30 self.source = source
31
32 def __str__(self) -> str:
33 base = super().__str__()
34 return f"{self.source}: {base}" if self.source else base
35
36
37 class BackendNotAvailableError(SwayError):
38 """A requested backend's optional dependencies aren't installed.
39
40 The CLI turns this into a pointed ``pip install dlm-sway[<extra>]``
41 hint; programmatic callers can read :attr:`extra` directly.
42 """
43
44 def __init__(self, backend: str, *, extra: str, hint: str | None = None) -> None:
45 message = (
46 f"backend {backend!r} unavailable — install the extra: pip install 'dlm-sway[{extra}]'"
47 )
48 if hint:
49 message = f"{message}\n{hint}"
50 super().__init__(message)
51 self.backend = backend
52 self.extra = extra
53
54
55 class ProbeError(SwayError):
56 """A probe failed to *execute* (as opposed to failing its assertion).
57
58 Distinct from a ``verdict=FAIL`` result — assertion failures are
59 normal and reported via :class:`ProbeResult`. This is for genuine
60 bugs: missing sections, mismatched tokenizers, NaN logits.
61 """
62
63 def __init__(self, probe: str, message: str) -> None:
64 super().__init__(f"probe {probe!r}: {message}")
65 self.probe = probe