def handleException(self, exc_info): 'See IPublisherResponse' # We want exception to be formatted to native strings. Pick # respective io class depending on python version. f = BytesIO() if PYTHON2 else StringIO() print_exception(exc_info[0], exc_info[1], exc_info[2], 100, f) self.setResult(f.getvalue())
def handleException(self, exc_info): 'See IPublisherResponse' # We want exception to be formatted to native strings. Pick # respective io class depending on python version. f = BytesIO() if PYTHON2 else StringIO() print_exception( exc_info[0], exc_info[1], exc_info[2], 100, f) self.setResult(f.getvalue())
def _callFUT(self, as_html=False): import io buf = io.StringIO() if bytes is not str else io.BytesIO() from zope.exceptions.exceptionformatter import print_exception t, v, b = sys.exc_info() try: print_exception(t, v, b, file=buf, as_html=as_html) return buf.getvalue() finally: del b
def formatException(self, ei): """Format and return the specified exception information as a string. Uses zope.exceptions.exceptionformatter to generate the traceback. """ sio = cStringIO.StringIO() print_exception(ei[0], ei[1], ei[2], file=sio, with_filenames=True) s = sio.getvalue() if s.endswith("\n"): s = s[:-1] return s
def _callFUT(self, as_html=False): try: from StringIO import StringIO except ImportError: from io import StringIO buf = StringIO() import sys from zope.exceptions.exceptionformatter import print_exception t, v, b = sys.exc_info() try: print_exception(t, v, b, file=buf, as_html=as_html) return buf.getvalue() finally: del b
def __call__(self, *args, **kwargs): # NOTE: We don't handle repoze.tm being in the pipeline number = self.attempts note = self.describe_transaction(*args, **kwargs) while number: number -= 1 tx = None # In case there's an exception /beginning/ the transaction, we still need the variable try: tx = transaction.begin() if note and note != "Unknown": tx.note(note) if self.attempts != 1: self.prep_for_retry(number, *args, **kwargs) result = self.run_handler(*args, **kwargs) # We should still have the same transaction. If we don't, # then we get a ValueError from tx.commit; however, we let this # pass if we would be aborting anyway. # assert transaction.get() is tx, "Started new transaction out from under us!" if self.should_abort_due_to_no_side_effects(*args, **kwargs): # These transactions can safely be aborted and ignored, reducing contention on commit locks # TODO: It would be cool to open them readonly in the first place. # TODO: I don't really know if this is kosher, but it does seem to work so far # NOTE: We raise these as an exception instead of aborting in the loop so that # we don't retry if something goes wrong aborting raise self.AbortException(result, "side-effect free") if tx.isDoomed() or self.should_veto_commit(result, *args, **kwargs): raise self.AbortException(result, "doomed or vetoed") # note: commit our tx variable, NOT what is current; if they aren't the same, this raises ValueError _do_commit(tx, note, self.long_commit_duration) self.__free(tx); del tx return result except self.AbortException as e: duration = _timing(transaction.abort, 'transaction.abort') # note: NOT our tx variable, whatever is current self.__free(tx); del tx logger.log(TRACE, "Aborted %s transaction for %s in %ss", e.reason, note, duration) return e.response except Exception as e: # pylint:disable=I0011,W0703 exc_info = sys.exc_info() # The code in the transaction package checks the retryable state # BEFORE aborting the current transaction. This matters because # aborting the transaction changes the transaction that the manager # has to a new one, and thus changes the set of registered resources # that participate in _retryable, depending on what synchronizers # are registered. retryable = self._retryable(exc_info) self._abort_on_exception(exc_info, retryable, number, tx) self.__free(tx); del tx del exc_info if number <= 0: # AFTER the abort raise if not retryable: raise if self.sleep: _sleep(self.sleep) # logger.log( TRACE, "Retrying transaction on exception %d", number, exc_info=True ) except SystemExit: if not sys: # pragma: no cover (module shutdown) raise # If we are exiting, or otherwise probably going to # exit, do try to abort the transaction. The state of # the system is somewhat undefined at this point, # though, so don't try to time or log it, just print # to stderr on exception. Be sure to reraise the # original SystemExit exc_info = sys.exc_info() try: transaction.abort() # note: NOT our tx variable, whatever is current except: # pylint:disable=I0011,W0702 if print_exception: print_exception(*sys.exc_info()) six.reraise(*exc_info)
def handleException(self, exc_info): 'See IPublisherResponse' f = StringIO() print_exception( exc_info[0], exc_info[1], exc_info[2], 100, f) self.setResult(f.getvalue())
def __call__(self, *args, **kwargs): # pylint:disable=too-many-branches,too-many-statements # NOTE: We don't handle repoze.tm being in the pipeline number = self.attempts note = self.describe_transaction(*args, **kwargs) # In case there's an exception /beginning/ the transaction, we still need the variable tx = None exc_info = None while number: number -= 1 # Throw away any previous exceptions our loop raised. # The TB could be taking lots of memory exc_clear() try: tx = transaction.begin() if note and note != "Unknown": tx.note(note) if self.attempts != 1: self.prep_for_retry(number, *args, **kwargs) result = self.run_handler(*args, **kwargs) # We should still have the same transaction. If we don't, # then we get a ValueError from tx.commit; however, we let this # pass if we would be aborting anyway. # assert transaction.get() is tx, "Started new transaction out from under us!" if self.should_abort_due_to_no_side_effects(*args, **kwargs): # These transactions can safely be aborted and ignored, reducing contention on commit locks # TODO: It would be cool to open them readonly in the first place. # TODO: I don't really know if this is kosher, but it does seem to work so far # NOTE: We raise these as an exception instead of aborting in the loop so that # we don't retry if something goes wrong aborting raise self.AbortException(result, "side-effect free") if tx.isDoomed() or self.should_veto_commit(result, *args, **kwargs): raise self.AbortException(result, "doomed or vetoed") # note: commit our tx variable, NOT what is current; if they aren't the same, this raises ValueError _do_commit(tx, note, self.long_commit_duration) self.__free(tx); del tx return result except self.AbortException as e: duration = _timing(transaction.abort, 'transaction.abort') # note: NOT our tx variable, whatever is current self.__free(tx); del tx logger.log(TRACE, "Aborted %s transaction for %s in %ss", e.reason, note, duration) return e.response except Exception as e: # pylint:disable=I0011,W0703 exc_info = sys.exc_info() # The code in the transaction package checks the retryable state # BEFORE aborting the current transaction. This matters because # aborting the transaction changes the transaction that the manager # has to a new one, and thus changes the set of registered resources # that participate in _retryable, depending on what synchronizers # are registered. retryable = self._retryable(tx, exc_info) self._abort_on_exception(exc_info, retryable, number, tx) self.__free(tx); del tx if number <= 0: # AFTER the abort raise if not retryable: raise if self.sleep: _sleep(self.sleep) # logger.log( TRACE, "Retrying transaction on exception %d", number, exc_info=True ) except SystemExit: if not sys: # pragma: no cover (module shutdown) raise # If we are exiting, or otherwise probably going to # exit, do try to abort the transaction. The state of # the system is somewhat undefined at this point, # though, so don't try to time or log it, just print # to stderr on exception. Be sure to reraise the # original SystemExit exc_info = sys.exc_info() try: transaction.abort() # note: NOT our tx variable, whatever is current except: # pylint:disable=I0011,W0702 if print_exception is not None: print_exception(*sys.exc_info()) six.reraise(*exc_info) finally: exc_info = None