def handleException(self, object, request, exc_info, retry_allowed=True): # This transaction had an exception that reached the publisher. # It must definitely be aborted. transaction.abort() # Convert ConflictErrors to Retry exceptions. if retry_allowed and isinstance(exc_info[1], ConflictError): tryToLogWarning('ZopePublication', 'Competing writes/reads at %s' % request.get('PATH_INFO', '???'), exc_info=True) raise Retry(exc_info) # Are there any reasons why we'd want to let application-level error # handling determine whether a retry is allowed or not? # Assume not for now. # Record the error with the ErrorReportingUtility self._logErrorWithErrorReportingUtility(object, request, exc_info) response = request.response response.reset() exception = None legacy_exception = not isinstance(exc_info[1], Exception) if legacy_exception: response.handleException(exc_info) if isinstance(exc_info[1], str): tryToLogWarning( 'Publisher received a legacy string exception: %s.' ' This will be handled by the request.' % exc_info[1]) else: tryToLogWarning( 'Publisher received a legacy classic class exception: %s.' ' This will be handled by the request.' % exc_info[1].__class__) else: # We definitely have an Exception # Set the request body, and abort the current transaction. self.beginErrorHandlingTransaction( request, object, 'application error-handling') view = None try: # We need to get a location, because some template content of # the exception view might require one. # # The object might not have a parent, because it might be a # method. If we don't have a `__parent__` attribute but have # an im_self or a __self__, use it. loc = object if not hasattr(object, '__parent__'): loc = removeSecurityProxy(object) # Try to get an object, since we apparently have a method # Note: We are guaranteed that an object has a location, # so just getting the instance the method belongs to is # sufficient. loc = getattr(loc, 'im_self', loc) loc = getattr(loc, '__self__', loc) # Protect the location with a security proxy loc = ProxyFactory(loc) # Give the exception instance its location and look up the # view. exception = LocationProxy(exc_info[1], loc, '') name = zapi.queryDefaultViewName(exception, request) if name is not None: view = zapi.queryMultiAdapter( (exception, request), name=name) except: # Problem getting a view for this exception. Log an error. tryToLogException( 'Exception while getting view on exception') if view is not None: try: # We use mapply instead of self.callObject here # because we don't want to pass positional # arguments. The positional arguments were meant # for the published object, not an exception view. body = mapply(view, (), request) response.setResult(body) transaction.commit() if (ISystemErrorView.providedBy(view) and view.isSystemError()): # Got a system error, want to log the error # Lame hack to get around logging missfeature # that is fixed in Python 2.4 try: raise exc_info[0], exc_info[1], exc_info[2] except: logging.getLogger('SiteError').exception( str(request.URL), ) except: # Problem rendering the view for this exception. # Log an error. tryToLogException( 'Exception while rendering view on exception') # Record the error with the ErrorReportingUtility self._logErrorWithErrorReportingUtility( object, request, sys.exc_info()) view = None if view is None: # Either the view was not found, or view was set to None # because the view couldn't be rendered. In either case, # we let the request handle it. response.handleException(exc_info) transaction.abort() # See if there's an IExceptionSideEffects adapter for the # exception try: adapter = IExceptionSideEffects(exception, None) except: tryToLogException( 'Exception while getting IExceptionSideEffects adapter') adapter = None if adapter is not None: self.beginErrorHandlingTransaction( request, object, 'application error-handling side-effect') try: # Although request is passed in here, it should be # considered read-only. adapter(object, request, exc_info) transaction.commit() except: tryToLogException( 'Exception while calling' ' IExceptionSideEffects adapter') transaction.abort()
def handleException(self, object, request, exc_info, retry_allowed=True): #orig = removeAllProxies(object) transaction.abort() if retry_allowed and isinstance(exc_info[1], Retry): raise if retry_allowed and isinstance(exc_info[1], ConflictError): tryToLogWarning( 'ZopePublication', 'Competing writes/reads at %s: %s' % (request.get('PATH_INFO', '???'), exc_info[1], ), ) raise Retry(exc_info) self._logErrorWithErrorReportingUtility(object, request, exc_info) response = request.response response.reset() exception = None legacy_exception = not isinstance(exc_info[1], Exception) if legacy_exception: response.handleException(exc_info) if isinstance(exc_info[1], str): tryToLogWarning( 'Publisher received a legacy string exception: %s.' ' This will be handled by the request.' % exc_info[1]) else: tryToLogWarning( 'Publisher received a legacy classic class exception: %s.' ' This will be handled by the request.' % exc_info[1].__class__) else: self.beginErrorHandlingTransaction( request, object, 'application error-handling') view = None try: loc = object if not hasattr(object, '__parent__'): loc = removeSecurityProxy(object) loc = getattr(loc, 'im_self', loc) loc = getattr(loc, '__self__', loc) loc = ProxyFactory(loc) exception = LocationProxy(exc_info[1], loc, '') name = queryDefaultViewName(exception, request) if name is not None: view = queryMultiAdapter( (exception, request), name=name) except: tryToLogException('Exception while getting view on exception') if view is not None: try: body = mapply(view, (), request) response.setResult(body) transaction.commit() if (ISystemErrorView.providedBy(view) and view.isSystemError()): try: raise exc_info[0], exc_info[1], exc_info[2] except: logging.getLogger('SiteError').exception( str(request.URL), ) except ReadOnlyError: transaction.abort() except: tryToLogException('Exception while rendering view on exception') self._logErrorWithErrorReportingUtility( object, request, sys.exc_info()) view = None if view is None: response.handleException(exc_info) transaction.abort() try: adapter = IExceptionSideEffects(exception, None) except: tryToLogException( 'Exception while getting IExceptionSideEffects adapter') adapter = None if adapter is not None: self.beginErrorHandlingTransaction( request, object, 'application error-handling side-effect') try: adapter(object, request, exc_info) transaction.commit() except ReadOnlyError: transaction.abort() except: tryToLogException('Exception while calling' ' IExceptionSideEffects adapter') transaction.abort()
def handleException(self, object, request, exc_info, retry_allowed=True): # This transaction had an exception that reached the publisher. # It must definitely be aborted. transaction.abort() # Reraise Retry exceptions for the publisher to deal with. if retry_allowed and isinstance(exc_info[1], Retry): raise # Convert ConflictErrors to Retry exceptions. if retry_allowed and isinstance(exc_info[1], ConflictError): tryToLogWarning( 'ZopePublication', 'Competing writes/reads at %s: %s' % ( request.get('PATH_INFO', '???'), exc_info[1], ), ) raise Retry(exc_info) # Are there any reasons why we'd want to let application-level error # handling determine whether a retry is allowed or not? # Assume not for now. # Record the error with the ErrorReportingUtility self._logErrorWithErrorReportingUtility(object, request, exc_info) response = request.response response.reset() exception = None legacy_exception = not isinstance(exc_info[1], Exception) if legacy_exception: response.handleException(exc_info) if isinstance(exc_info[1], str): tryToLogWarning( 'Publisher received a legacy string exception: %s.' ' This will be handled by the request.' % exc_info[1]) else: tryToLogWarning( 'Publisher received a legacy classic class exception: %s.' ' This will be handled by the request.' % exc_info[1].__class__) else: # We definitely have an Exception # Set the request body, and abort the current transaction. self.beginErrorHandlingTransaction(request, object, 'application error-handling') view = None try: # We need to get a location, because some template content of # the exception view might require one. # # The object might not have a parent, because it might be a # method. If we don't have a `__parent__` attribute but have # an im_self or a __self__, use it. loc = object if not hasattr(object, '__parent__'): loc = removeSecurityProxy(object) # Try to get an object, since we apparently have a method # Note: We are guaranteed that an object has a location, # so just getting the instance the method belongs to is # sufficient. loc = getattr(loc, 'im_self', loc) loc = getattr(loc, '__self__', loc) # Protect the location with a security proxy loc = ProxyFactory(loc) # Give the exception instance its location and look up the # view. exception = LocationProxy(exc_info[1], loc, '') name = queryDefaultViewName(exception, request) if name is not None: view = zope.component.queryMultiAdapter( (exception, request), name=name) except: # Problem getting a view for this exception. Log an error. tryToLogException('Exception while getting view on exception') if view is not None: try: # We use mapply instead of self.callObject here # because we don't want to pass positional # arguments. The positional arguments were meant # for the published object, not an exception view. body = mapply(view, (), request) response.setResult(body) transaction.commit() if (ISystemErrorView.providedBy(view) and view.isSystemError()): # Got a system error, want to log the error # Lame hack to get around logging missfeature # that is fixed in Python 2.4 try: raise exc_info[0], exc_info[1], exc_info[2] except: logging.getLogger('SiteError').exception( str(request.URL), ) except: # Problem rendering the view for this exception. # Log an error. tryToLogException( 'Exception while rendering view on exception') # Record the error with the ErrorReportingUtility self._logErrorWithErrorReportingUtility( object, request, sys.exc_info()) view = None if view is None: # Either the view was not found, or view was set to None # because the view couldn't be rendered. In either case, # we let the request handle it. response.handleException(exc_info) transaction.abort() # See if there's an IExceptionSideEffects adapter for the # exception try: adapter = IExceptionSideEffects(exception, None) except: tryToLogException( 'Exception while getting IExceptionSideEffects adapter') adapter = None if adapter is not None: self.beginErrorHandlingTransaction( request, object, 'application error-handling side-effect') try: # Although request is passed in here, it should be # considered read-only. adapter(object, request, exc_info) transaction.commit() except: tryToLogException('Exception while calling' ' IExceptionSideEffects adapter') transaction.abort()