Bare "except" dangerous to ZODB? was Re: [Zope-dev] Accept-Charset hearders causing 500 internal server error.[correct but not lenient]
Toby Dickenson
tdickenson@geminidataloggers.com
Tue, 11 Feb 2003 10:51:38 +0000
--Boundary-00=_6WNS+C56xTSEENN
Content-Type: text/plain;
charset="iso-8859-1"
Content-Transfer-Encoding: 7bit
Content-Disposition: inline
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.
--Boundary-00=_6WNS+C56xTSEENN
Content-Type: text/x-python;
charset="iso-8859-1";
name="Veto.py"
Content-Transfer-Encoding: 7bit
Content-Disposition: attachment; filename="Veto.py"
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))
--Boundary-00=_6WNS+C56xTSEENN--