def __before_publishing_traverse__(self, arg1, arg2=None): """ Pre-traversal hook. """ # XXX hack around a bug(?) in BeforeTraverse.MultiHook REQUEST = arg2 or arg1 if REQUEST['REQUEST_METHOD'] not in ('GET', 'POST'): return stack = REQUEST['TraversalRequestNameStack'] key = stack and stack[-1] or '(Default)' # if there's a Zope3-style default view name set and the # corresponding view exists, take that in favour of the FTI's # default view if key == '(Default)': viewname = queryDefaultViewName(self, REQUEST) if (viewname and queryMultiAdapter((self, REQUEST), name=viewname) is not None): stack.append(viewname) REQUEST._hacked_path = 1 return ti = self.getTypeInfo() method_id = ti and ti.queryMethodID(key, context=self) if method_id: if key != '(Default)': stack.pop() if method_id != '(Default)': stack.append(method_id) REQUEST._hacked_path = 1
def __before_publishing_traverse__(self, arg1, arg2=None): """ Pre-traversal hook. """ # XXX hack around a bug(?) in BeforeTraverse.MultiHook REQUEST = arg2 or arg1 if REQUEST['REQUEST_METHOD'] not in ('GET', 'POST'): return stack = REQUEST['TraversalRequestNameStack'] key = stack and stack[-1] or '(Default)' # if there's a Zope3-style default view name set and the # corresponding view exists, take that in favour of the FTI's # default view if key == '(Default)': viewname = queryDefaultViewName(self, REQUEST) if (viewname and queryMultiAdapter( (self, REQUEST), name=viewname) is not None): stack.append(viewname) REQUEST._hacked_path = 1 return ti = self.getTypeInfo() method_id = ti and ti.queryMethodID(key, context=self) if method_id: if key != '(Default)': stack.pop() if method_id != '(Default)': stack.append(method_id) REQUEST._hacked_path = 1
def add_container_menu_items(self, context, container): request = self.request _url = url.absoluteURL(container, request) if IReadContainer.providedBy(container): #XXX should be the same in all containers ? container = proxy.removeSecurityProxy(container) for name, item in container.items(): if context is None: selected = False else: selected = url.same_path_names(context.__name__, name) item = proxy.removeSecurityProxy(item) if IDCDescriptiveProperties.providedBy(item): title = item.title else: props = IDCDescriptiveProperties(item) title = props.title # only items with valid title if title is not None: self.items.append( url.get_menu_item_descriptor(title, selected, _url, name)) default_view_name = queryDefaultViewName(container, self.request) default_view = component.queryMultiAdapter((container, self.request), name=default_view_name) if hasattr(default_view, "title") and default_view.title is not None: self.items.insert( 0, url.get_menu_item_descriptor( default_view.title, sameProxiedObjects(container, self.context), _url))
def add_container_menu_items(self, context, container): request = self.request _url = url.absoluteURL(container, request) if IReadContainer.providedBy(container): #XXX should be the same in all containers ? container=proxy.removeSecurityProxy(container) for name, item in container.items(): if context is None: selected = False else: selected = url.same_path_names(context.__name__, name) item = proxy.removeSecurityProxy(item) if IDCDescriptiveProperties.providedBy(item): title = item.title else: props = IDCDescriptiveProperties(item) title = props.title # only items with valid title if title is not None: self.items.append(url.get_menu_item_descriptor( title, selected, _url, name)) default_view_name = queryDefaultViewName(container, self.request) default_view = component.queryMultiAdapter( (container, self.request), name=default_view_name) if hasattr(default_view, "title") and default_view.title is not None: self.items.insert(0, url.get_menu_item_descriptor( default_view.title, sameProxiedObjects(container, self.context), _url))
def update(self): self.items = [] for item in self.context.values(): name = queryDefaultViewName(item, self.request, self.context) if name is not None: view = queryMultiAdapter((item, self.request), name=name) if view is not None and IPage.providedBy(view): view.update() self.items.append(view.content())
def add_container_menu_items(self, context, container): request = self.request # add a menu item for each user workspace, if we are in an # IWorkspaceSectionLayer # !+ if user is logged in or if request.layer_data if (interfaces.IWorkspaceSectionLayer.providedBy(request) or interfaces.IWorkspaceSchedulingSectionLayer.providedBy( request)): try: workspaces = IAnnotations(request)["layer_data"].get( "workspaces") except: workspaces = [] log.info("%s got user workspaces: %s" % (self, workspaces)) base_url_path = "/workspace" for workspace in workspaces: log.info("appending menu item for user workspace: %s" % (workspace)) self.items.append( url.get_menu_item_descriptor( workspace.full_name, pos_action_in_url( "/workspace/obj-%s" % workspace.group_id, request.getURL()), base_url_path, "obj-%s" % workspace.group_id)) _url = url.absoluteURL(container, request) if IReadContainer.providedBy(container): #XXX should be the same in all containers ? container = proxy.removeSecurityProxy(container) for name, item in container.items(): if context is None: selected = False else: selected = url.same_path_names(context.__name__, name) item = proxy.removeSecurityProxy(item) if IDCDescriptiveProperties.providedBy(item): title = item.title else: props = IDCDescriptiveProperties(item) title = props.title # only items with valid title if title is not None: self.items.append( url.get_menu_item_descriptor(title, selected, _url, name)) default_view_name = queryDefaultViewName(container, self.request) default_view = component.queryMultiAdapter((container, self.request), name=default_view_name) if hasattr(default_view, "title") and default_view.title is not None: self.items.insert( 0, url.get_menu_item_descriptor( default_view.title, sameProxiedObjects(container, self.context), _url))
def browserDefault(self, request): if hasattr(self.context, '__browser_default__'): return self.context.__browser_default__(request) # Zope 3.2 still uses IDefaultView name when it # registeres default views, even though it's # deprecated. So we handle that here: default_name = queryDefaultViewName(self.context, request) if default_name is not None: # Adding '@@' here forces this to be a view. # A neater solution might be desireable. return self.context, ('@@' + default_name, ) return self.context, ()
def browserDefault(self, request): if hasattr(self.context, '__browser_default__'): return self.context.__browser_default__(request) # Zope 3.2 still uses IDefaultView name when it # registeres default views, even though it's # deprecated. So we handle that here: default_name = queryDefaultViewName(self.context, request) if default_name is not None: # Adding '@@' here forces this to be a view. # A neater solution might be desireable. return self.context, ('@@' + default_name,) return self.context, ()
def add_container_menu_items(self, context, container): request = self.request # add a menu item for each user workspace, if we are in an # IWorkspaceSectionLayer # !+ if user is logged in or if request.layer_data if (interfaces.IWorkspaceSectionLayer.providedBy(request) or interfaces.IWorkspaceSchedulingSectionLayer.providedBy(request) ): try: workspaces = IAnnotations(request)["layer_data"].get("workspaces") except: workspaces = [] log.info("%s got user workspaces: %s" % (self, workspaces)) base_url_path = "/workspace" for workspace in workspaces: log.info("appending menu item for user workspace: %s" % ( workspace)) self.items.append(url.get_menu_item_descriptor( workspace.full_name, pos_action_in_url("/workspace/obj-%s" % workspace.group_id, request.getURL()), base_url_path, "obj-%s" % workspace.group_id)) _url = url.absoluteURL(container, request) if IReadContainer.providedBy(container): #XXX should be the same in all containers ? container=proxy.removeSecurityProxy(container) for name, item in container.items(): if context is None: selected = False else: selected = url.same_path_names(context.__name__, name) item = proxy.removeSecurityProxy(item) if IDCDescriptiveProperties.providedBy(item): title = item.title else: props = IDCDescriptiveProperties(item) title = props.title # only items with valid title if title is not None: self.items.append(url.get_menu_item_descriptor( title, selected, _url, name)) default_view_name = queryDefaultViewName(container, self.request) default_view = component.queryMultiAdapter( (container, self.request), name=default_view_name) if hasattr(default_view, "title") and default_view.title is not None: self.items.insert(0, url.get_menu_item_descriptor( default_view.title, sameProxiedObjects(container, self.context), _url))
def add_zcml_menu_items(self, container): """Add the list of ZCML menu items (if any) for this top-level container. Top-level section given by container may define a menu in ZCML with naming convention: <container_name>_navigation. """ # !+ turn this into a utility zcml_menu_name_template = "%s_navigation" try: menu_name = zcml_menu_name_template % container.__name__ menu = component.getUtility(IBrowserMenu, name=menu_name) items = menu.getMenuItems(container, self.request) except (Exception, ): debug.log_exc(sys.exc_info(), log_handler=log.debug) return [] # OK, do any necessary post-processing of each menu item local_url = url.absoluteURL(container, self.request) site_url = url.absoluteURL(getSite(), self.request) request_url = self.request.getURL() default_view_name = queryDefaultViewName(container, self.request) selection = None for item in sorted(items, key=lambda item: item["action"], reverse=True): action = item["action"] if default_view_name == action.lstrip("@@"): _url = local_url if selection is None: selected = sameProxiedObjects(container, self.context) else: _url = make_absolute(action, local_url, site_url) if selection is None: selected = pos_action_in_url(action, request_url) item["url"] = _url item["selected"] = selected and u"selected" or u"" if selected: # self is marker selection = self selected = False self.items.append(item)
def add_zcml_menu_items(self, container): """Add the list of ZCML menu items (if any) for this top-level container. Top-level section given by container may define a menu in ZCML with naming convention: <container_name>_navigation. """ # !+ turn this into a utility zcml_menu_name_template = "%s_navigation" try: menu_name = zcml_menu_name_template % container.__name__ menu = component.getUtility(IBrowserMenu, name=menu_name) items = menu.getMenuItems(container, self.request) except (Exception,): debug.log_exc(sys.exc_info(), log_handler=log.debug) return [] # OK, do any necessary post-processing of each menu item local_url = url.absoluteURL(container, self.request) site_url = url.absoluteURL(getSite(), self.request) request_url = self.request.getURL() default_view_name = queryDefaultViewName(container, self.request) selection = None for item in sorted(items, key=lambda item: item["action"], reverse=True): action = item["action"] if default_view_name==action.lstrip("@@"): _url = local_url if selection is None: selected = sameProxiedObjects(container, self.context) else: _url = make_absolute(action, local_url, site_url) if selection is None: selected = pos_action_in_url(action, request_url) item["url"] = _url item["selected"] = selected and u"selected" or u"" if selected: # self is marker selection = self selected = False self.items.append(item)
def handleException(self, object, request, exc_info, retry_allowed=True): # This transaction had an exception that reached the publisher. # It must definitely be aborted. try: transaction.abort() except: # Hm, a catastrophe. We might want to know what preceded it. self._logErrorWithErrorReportingUtility(object, request, exc_info) raise # Reraise Retry exceptions for the publisher to deal with. if retry_allowed and isinstance(exc_info[1], Retry): raise # Convert ConflictErrors to Retry exceptions. # where transaction.interfaces.TransientError is a more generic exception if retry_allowed and isinstance(exc_info[1], transaction.interfaces.TransientError): 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 = self.proxy(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: body = self.callErrorView(request, view) 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): # This transaction had an exception that reached the publisher. # It must definitely be aborted. try: transaction.abort() except: # Hm, a catastrophe. We might want to know what preceded it. self._logErrorWithErrorReportingUtility(object, request, exc_info) raise # 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 = self.proxy(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()