示例#1
0
    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
示例#2
0
    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
示例#3
0
    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))
示例#4
0
 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())
示例#6
0
    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))
示例#7
0
 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, ()
示例#8
0
 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, ()
示例#9
0
 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))
示例#10
0
    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)
示例#11
0
 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()
示例#13
0
    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()