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