feat(errors): stable machine-readable codes on IngestError

Consumer tests were binding message wording (pytest.raises(match=...)) to
distinguish sub-causes within one error type. Every raise site now carries
a documented, stable code attribute; the registry lives in the errors.py
class docstrings. Codes are stable API; message text is explicitly not.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
This commit is contained in:
Kjell Tore Guttormsen 2026-07-17 04:01:04 +02:00
commit 9d296ca686
6 changed files with 468 additions and 43 deletions

View file

@ -22,7 +22,10 @@ def sql_value_to_text(value: object) -> str:
if value is None:
return ""
if isinstance(value, bool):
raise RenderError(f"unsupported SQL cell type bool ({value!r}) — never silent coercion")
raise RenderError(
f"unsupported SQL cell type bool ({value!r}) — never silent coercion",
code="unsupported_cell_type",
)
if isinstance(value, int):
return str(value)
if isinstance(value, float):
@ -31,7 +34,8 @@ def sql_value_to_text(value: object) -> str:
return value
raise RenderError(
f"unsupported SQL cell type {type(value).__name__} — spec §5 allows "
"integer/float/text/NULL only; never silent coercion"
"integer/float/text/NULL only; never silent coercion",
code="unsupported_cell_type",
)