On Monday 10 February 2003 8:47 pm, Shane Hathaway wrote: > > Great, so there's at least 133 things to examine to see if they > > could catch a ConflictError. And I only wrote about 15 of those. > > The rest could be very time-consuming to audit. > > "tal:on-error" also catches all exceptions. It could be made to catch > all exceptions except ConflictError, but I don't feel like that's the > right solution.
A while ago I tracked down a bug in one of our products to a case where a mutator method failed half way. It raised an exception and left the object in an invalid state. This would be safe except for a dtml-try that swallowed the exception. Recently I have been experimenting with this attached module to ensure that an application-level object can veto a transaction. I guess it would be applicable to ConflicctErrors too.
from zLOG import LOG, WARNING, ERROR class _veto: def __init__(self,msg): self.msg = msg def sortKey(self): return repr(self) def _do_nothing(self,*args): pass tpc_finish = tpc_abort = abort = abort_sub = _do_nothing def _veto(self,*args): try: LOG('Veto', ERROR, self.msg) except: pass raise TranactionVetoError(self.msg) __getstate__ = tpc_begin = commit = tpc_vote = commit_sub = _veto class TranactionVetoError(Exception): pass def veto(msg=None,ob=None): """Call this if your object is in an invalid state, it is about to raise an exception, and you want to be sure that the current transaction does not complete even if something swallows that exception. msg - An error message describing the problem. optional. ob - The object which is now invalid. optional. If specified, the transaction will only abort if this object is persisted. """ m = 'This transaction had been vetoed following a previous error' if ob is not None: try: m += ' in '+str(ob) except: m += ' in <unprintable object>' if msg is not None: try: m += ':\n'+str(msg) except: m += ':\nunprintable error' print 'nnn',m if ob is not None: try: ob._transaction_veto_attribute_that_can_not_be_persisted = _veto(m) except: pass else: return # Drop through if we can not set our veto attribute on that object, # or if no object was specified get_transaction().register(_veto(m))