diff --git a/grblas/base.py b/grblas/base.py index ed28990ad..4f8f81e76 100644 --- a/grblas/base.py +++ b/grblas/base.py @@ -41,7 +41,14 @@ def call(cfunc_name, args): f" - C signature: {sig}\n" f" - Error: {exc}" ) - rv = check_status(err_code, args) + try: + rv = check_status(err_code, args) + except Exception as exc: + # Record calls that fail for easier debugging + rec = _recorder.get(_prev_recorder) + if rec is not None: + rec.record(cfunc_name, args, exc=exc) + raise rec = _recorder.get(_prev_recorder) if rec is not None: rec.record(cfunc_name, args) diff --git a/grblas/recorder.py b/grblas/recorder.py index e8caa48d3..ad89d8322 100644 --- a/grblas/recorder.py +++ b/grblas/recorder.py @@ -53,10 +53,13 @@ def __init__(self, *, start=True, max_rows=20): if start: self.start() - def record(self, cfunc_name, args): + def record(self, cfunc_name, args, *, exc=None): if not hasattr(lib, cfunc_name): cfunc_name = f"GxB_{cfunc_name[4:]}" - self.data.append(f'{cfunc_name}({", ".join(gbstr(x) for x in args)});') + val = f'{cfunc_name}({", ".join(gbstr(x) for x in args)});' + if exc is not None: + val += f" /* ERROR: {type(exc).__name__} */" + self.data.append(val) base._prev_recorder = self def record_raw(self, text): diff --git a/grblas/tests/test_recorder.py b/grblas/tests/test_recorder.py index c464b8ee4..4f412172e 100644 --- a/grblas/tests/test_recorder.py +++ b/grblas/tests/test_recorder.py @@ -1,4 +1,5 @@ import grblas as gb +from grblas.exceptions import OutOfMemory from grblas.formatting import CSS_STYLE @@ -138,3 +139,16 @@ def test_record_repr_markdown(): "\n" "" ) + + +def test_record_failed_call(): + BIG = gb.Vector.new(int, size=2 ** 55) + small = gb.Vector.new(int, size=2 ** 55) + BIG[:] = 1 + small[0] = 2 + rec = gb.Recorder() + try: + BIG.ewise_add(small).new() + except OutOfMemory: + pass + assert "ERROR: OutOfMemory" in rec.data[-1]