def transaction_pubevents(request, tm=transaction.manager): ok_exception = None try: setDefaultSkin(request) newInteraction() tm.begin() notify(pubevents.PubStart(request)) try: yield None except (HTTPOk, HTTPRedirection) as exc: ok_exception = exc notify(pubevents.PubBeforeCommit(request)) if tm.isDoomed(): tm.abort() else: tm.commit() notify(pubevents.PubSuccess(request)) except Exception: exc_info = sys.exc_info() notify( pubevents.PubBeforeAbort(request, exc_info, request.supports_retry())) tm.abort() notify( pubevents.PubFailure(request, exc_info, request.supports_retry())) raise finally: endInteraction() if ok_exception is not None: raise ok_exception
def transaction_pubevents(request, response, tm=transaction.manager): try: setDefaultSkin(request) newInteraction() tm.begin() notify(pubevents.PubStart(request)) yield notify(pubevents.PubBeforeCommit(request)) if tm.isDoomed(): tm.abort() else: tm.commit() notify(pubevents.PubSuccess(request)) except Exception as exc: # Normalize HTTP exceptions # (For example turn zope.publisher NotFound into zExceptions NotFound) exc_type, _ = upgradeException(exc.__class__, None) if not isinstance(exc, exc_type): exc = exc_type(str(exc)) # Create new exc_info with the upgraded exception. exc_info = (exc_type, exc, sys.exc_info()[2]) try: # Raise exception from app if handle-errors is False # (set by zope.testbrowser in some cases) if request.environ.get('x-wsgiorg.throw_errors', False): reraise(*exc_info) if isinstance(exc, Unauthorized): # _unauthorized modifies the response in-place. If this hook # is used, an exception view for Unauthorized has to merge # the state of the response and the exception instance. exc.setRealm(response.realm) response._unauthorized() response.setStatus(exc.getStatus()) # Handle exception view exc_view_created = _exc_view_created_response( exc, request, response) notify( pubevents.PubBeforeAbort(request, exc_info, request.supports_retry())) tm.abort() notify( pubevents.PubFailure(request, exc_info, request.supports_retry())) if not (exc_view_created or isinstance(exc, Unauthorized)): reraise(*exc_info) finally: # Avoid traceback / exception reference cycle. del exc, exc_info finally: endInteraction()
def publish( request, module_name, after_list, debug=0, # Optimize: call_object=call_object, missing_name=missing_name, dont_publish_class=dont_publish_class, mapply=mapply, ): (bobo_before, bobo_after, object, realm, debug_mode, err_hook, validated_hook, transactions_manager) = get_module_info(module_name) parents = None response = None try: notify(pubevents.PubStart(request)) # TODO pass request here once BaseRequest implements IParticipation newInteraction() request.processInputs() request_get = request.get response = request.response # First check for "cancel" redirect: if request_get('SUBMIT', '').strip().lower() == 'cancel': cancel = request_get('CANCEL_ACTION', '') if cancel: # Relative URLs aren't part of the spec, but are accepted by # some browsers. for part, base in zip( urlparse(cancel)[:3], urlparse(request['BASE1'])[:3]): if not part: continue if not part.startswith(base): cancel = '' break if cancel: raise Redirect(cancel) after_list[0] = bobo_after if debug_mode: response.debug_mode = debug_mode if realm and not request.get('REMOTE_USER', None): response.realm = realm noSecurityManager() if bobo_before is not None: bobo_before() # Get the path list. # According to RFC1738 a trailing space in the path is valid. path = request_get('PATH_INFO') request['PARENTS'] = parents = [object] if transactions_manager: transactions_manager.begin() object = request.traverse(path, validated_hook=validated_hook) if IBrowserPage.providedBy(object): request.postProcessInputs() notify(pubevents.PubAfterTraversal(request)) if transactions_manager: recordMetaData(object, request) result = mapply(object, request.args, request, call_object, 1, missing_name, dont_publish_class, request, bind=1) if result is not response: response.setBody(result) notify(pubevents.PubBeforeCommit(request)) if transactions_manager: transactions_manager.commit() notify(pubevents.PubSuccess(request)) endInteraction() return response except: # save in order to give 'PubFailure' the original exception info exc_info = sys.exc_info() # DM: provide nicer error message for FTP sm = None if response is not None: sm = getattr(response, "setMessage", None) if sm is not None: from asyncore import compact_traceback cl, val = sys.exc_info()[:2] sm('%s: %s %s' % (getattr(cl, '__name__', cl), val, debug_mode and compact_traceback()[-1] or '')) # debug is just used by tests (has nothing to do with debug_mode!) if not debug and err_hook is not None: retry = False if parents: parents = parents[0] try: try: return err_hook( parents, request, sys.exc_info()[0], sys.exc_info()[1], sys.exc_info()[2], ) except Retry: if not request.supports_retry(): return err_hook( parents, request, sys.exc_info()[0], sys.exc_info()[1], sys.exc_info()[2], ) retry = True finally: # Note: 'abort's can fail. # Nevertheless, we want end request handling. try: try: notify( pubevents.PubBeforeAbort(request, exc_info, retry)) finally: if transactions_manager: transactions_manager.abort() finally: endInteraction() notify(pubevents.PubFailure(request, exc_info, retry)) # Only reachable if Retry is raised and request supports retry. newrequest = request.retry() request.close() # Free resources held by the request. # Set the default layer/skin on the newly generated request if ISkinnable.providedBy(newrequest): setDefaultSkin(newrequest) try: return publish(newrequest, module_name, after_list, debug) finally: newrequest.close() else: # Note: 'abort's can fail. # Nevertheless, we want end request handling. try: try: notify(pubevents.PubBeforeAbort(request, exc_info, False)) finally: if transactions_manager: transactions_manager.abort() finally: endInteraction() notify(pubevents.PubFailure(request, exc_info, False)) raise
def transaction_pubevents(request, response, tm=transaction.manager): try: setDefaultSkin(request) newInteraction() tm.begin() notify(pubevents.PubStart(request)) yield notify(pubevents.PubBeforeCommit(request)) if tm.isDoomed(): tm.abort() else: tm.commit() notify(pubevents.PubSuccess(request)) except Exception as exc: # Normalize HTTP exceptions # (For example turn zope.publisher NotFound into zExceptions NotFound) exc_type, _ = upgradeException(exc.__class__, None) if not isinstance(exc, exc_type): exc = exc_type(str(exc)) # Create new exc_info with the upgraded exception. exc_info = (exc_type, exc, sys.exc_info()[2]) try: # Raise exception from app if handle-errors is False # (set by zope.testbrowser in some cases) if request.environ.get('x-wsgiorg.throw_errors', False): reraise(*exc_info) retry = False unauth = False debug_exc = getattr(response, 'debug_exceptions', False) # If the exception is transient and the request can be retried, # shortcut further processing. It makes no sense to have an # exception view registered for this type of exception. if isinstance(exc, TransientError) and request.supports_retry(): retry = True else: # Handle exception view. Make sure an exception view that # blows up doesn't leave the user e.g. unable to log in. try: exc_view_created = _exc_view_created_response( exc, request, response) except Exception: exc_view_created = False # _unauthorized modifies the response in-place. If this hook # is used, an exception view for Unauthorized has to merge # the state of the response and the exception instance. if isinstance(exc, Unauthorized): unauth = True exc.setRealm(response.realm) response._unauthorized() response.setStatus(exc.getStatus()) # Notify subscribers that this request is failing. notify(pubevents.PubBeforeAbort(request, exc_info, retry)) tm.abort() notify(pubevents.PubFailure(request, exc_info, retry)) if retry or \ (not unauth and (debug_exc or not exc_view_created)): reraise(*exc_info) finally: # Avoid traceback / exception reference cycle. del exc, exc_info finally: endInteraction()