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--