open-standards/wai/wai-quantum-py/python/wai_quantum/errors.py
Transaction Science eb6e4006c0 wai-quantum-py: wai_quantum.verdict and repair, run with an intent, and job.verdict
run and job_request take intent, verdict and repair, and Job.verdict reads
the verdict the receipt seals. verdict() gives a job's verdict, its own or
one worked out here for another intent (marked not sealed); repair() makes
the mechanical fixes on the flagged lines and refuses a proposal that changes
another line. EngineError's code reads the job layer's codes as well as the
reader's. The getting-started notebook's stored refusal carries its J011.

Co-Authored-By: Claude Opus 5.5 <[email protected]>
2026-10-27 23:44:27 -04:00

56 lines
2 KiB
Python

"""What the package raises: the engine's refusals and the service's."""
from __future__ import annotations
import re
from typing import Any, Optional
__all__ = ["EngineError", "ServiceError"]
_LINE = re.compile(r"^line (\d+):")
_CODE = re.compile(r"\[([QJ]\d{3})\]$")
class EngineError(Exception):
"""The engine refused a request, a program or a value, and said why.
``message`` is the engine's message as it gave it, the same text the
command line, the service and the Studio show. ``line`` is the program's
line the message names, when it names one. ``code`` is the stable code
the refusal ends with: the reader's (``"Q103"``), or the job layer's
(``"J011"``: the request, the method, an intent, a repair); code that
handles errors should test it, not the message.
"""
def __init__(self, message: str, code: Optional[str] = None, line: Optional[int] = None) -> None:
super().__init__(message)
self.message = message
if code is None:
m = _CODE.search(message)
code = m.group(1) if m else None
self.code = code
if line is None:
m = _LINE.match(message)
line = int(m.group(1)) if m else None
self.line = line
def __reduce__(self):
return (type(self), (self.message, self.code, self.line))
class ServiceError(Exception):
"""The job service refused a request, a job failed or was cancelled, or
the service could not be reached.
``status`` is the HTTP status (``None`` when no answer came), ``message``
the service's own words, and ``body`` its whole answer when it sent one.
"""
def __init__(self, message: str, status: Optional[int] = None, body: Any = None) -> None:
super().__init__(message if status is None else f"{message} (HTTP {status})")
self.message = message
self.status = status
self.body = body
def __reduce__(self):
return (type(self), (self.message, self.status, self.body))