.begin(), .commit(), .rollback() and a work callable. Write transact(db, work) implementing the classic pattern: begin, run work, commit and return its result — but on ANY exception roll back first, then re-raise. If the rollback itself raises, let the original work exception win (suppress the rollback error).transact(db, lambda: save())
result of save(), committed — or rolled back + original error re-raised
Rollback failures never mask the real cause.
Nest a try/except Exception: pass around the rollback call.
A bare raise after the inner try re-raises the original.