Ejemplo n.º 1
0
    def render_content_provider(econtext, name):
        name = name.strip()

        context = econtext.get('context')
        request = econtext.get('request')
        view = econtext.get('view')

        cp = queryMultiAdapter((context, request, view),
                               IContentProvider,
                               name=name)

        # provide a useful error message, if the provider was not found.
        if cp is None:
            raise ContentProviderLookupError(name)

        # add the __name__ attribute if it implements ILocation
        if ILocation.providedBy(cp):
            cp.__name__ = name

        # Insert the data gotten from the context
        addTALNamespaceData(cp, econtext)

        # BBB: This is where we're different:
        if getattr(cp, '__of__', None) is not None:
            cp = cp.__of__(context)

        # Stage 1: Do the state update.
        if BeforeUpdateEvent is not None:
            notify(BeforeUpdateEvent(cp, request))
        cp.update()

        # Stage 2: Render the HTML content.
        return cp.render()
Ejemplo n.º 2
0
def render_content_provider(econtext, name):
    name = name.strip()

    context = econtext.get("context")
    request = econtext.get("request")
    view = econtext.get("view")

    cp = zope.component.queryMultiAdapter((context, request, view),
                                          IContentProvider,
                                          name=name)

    # provide a useful error message, if the provider was not found.
    # Be sure to provide the objects in addition to the name so
    # debugging ZCML registrations is possible
    if cp is None:
        raise ContentProviderLookupError(name, (context, request, view))

    # add the __name__ attribute if it implements ILocation
    if ILocation.providedBy(cp):
        cp.__name__ = name

    # Insert the data gotten from the context
    addTALNamespaceData(cp, econtext)

    # Stage 1: Do the state update.
    zope.event.notify(BeforeUpdateEvent(cp, request))
    cp.update()

    # Stage 2: Render the HTML content.
    return cp.render()
Ejemplo n.º 3
0
    def update(self):
        """See zope.contentprovider.interfaces.IContentProvider"""
        #--=mpj17=-- Stolen from zope.viewlet.manager
        self.__updated = True
        # Find all content providers for the region
        viewlets = getAdapters(
            (self.context, self.request, self.__parent__, self),
            interfaces.IViewlet)
        viewlets = self.filter_out_no_shows(viewlets)

        # --=mpj17=-- This is the main change to the standard viewlet
        #       manager: the viewlets are sorted according to the
        #       "weight" attribute
        viewlets.sort(key=lambda v: int(v[1].weight))

        self.viewlets = []
        for name, viewlet in viewlets:
            if ILocation.providedBy(viewlet):
                viewlet.__name__ = name
            self.viewlets.append(viewlet)
            # --=mpj17=-- Don't call _updateViewlets, because it does
            #       not exist in Zope 2.10
            if zope213:
                notify(BeforeUpdateEvent(viewlet, self.request))
            viewlet.update()
Ejemplo n.º 4
0
 def update(self):
     """See :py:class:`zope.contentprovider.interfaces.IContentProvider`"""
     registry = self.request.registry
     registry.notify(BeforeUpdateEvent(self, self.request))
     # check permission
     if self.permission and not self.request.has_permission(
             self.permission, context=self.context):
         return
     # get the viewlets from now on
     self.viewlets = []
     append = self.viewlets.append
     for name, viewlet in self._get_viewlets():
         if ILocation.providedBy(viewlet):
             viewlet.__name__ = name
         append(viewlet)
     # and update them...
     self._update_viewlets()
     self.__updated = True
Ejemplo n.º 5
0
 def _update_viewlets(self):
     """Calls update on all viewlets and fires events"""
     registry = self.request.registry
     for viewlet in self.viewlets:
         registry.notify(BeforeUpdateEvent(viewlet, self.request))
         viewlet.update()
Ejemplo n.º 6
0
 def _updateViewlets(self):
     """Calls update on all viewlets and fires events"""
     for viewlet in self.viewlets:
         zope.event.notify(BeforeUpdateEvent(viewlet, self.request))
         viewlet.update()
Ejemplo n.º 7
0
def render_content_provider(econtext, name):  # pylint: disable=too-many-locals,too-many-statements
    """TALES provider: content provider

    This TALES expression is used to render a registered "content provider", which
    is an adapter providing IContentProvider interface; adapter lookup is based on
    current context, request and view.

    The requested provider can be called with our without arguments, like in
    ${structure:provider:my_provider} or ${structure:provider:my_provider(arg1, arg2)}.
    In the second form, arguments will be passed to the "update" method; arguments can be
    static (like strings or integers), or can be variables defined into current template
    context; other Python expressions including computations or functions calls are actually
    not supported, but dotted syntax is supported to access inner attributes of variables.

    Provider arguments can be passed by position but can also be passed by name, using classic
    syntax as in ${structure:provider:my_provider(arg1, arg3=var3)}
    """

    def get_provider(name):
        # we first look into request annotations to check if a provider implementation has
        # already been provided during traversal; if not, a simple adapter lookup is done
        provider = get_request_data(request, 'provider:{}:factory'.format(name))

        # if using request annotations, provider can be given as a "direct" factory or as a
        # dict; if a dict is provided, it's keys are interfaces or classes that the current
        # context class have to provide or inherit from, and it's matching values are the
        # provider factories.
        # if provider is given as a dict, it should be ordered using an OrderedDict so thet
        # more specific interfaces are provided first!
        if isinstance(provider, dict):
            for intf, factory in provider.items():
                if (is_interface(intf) and intf.providedBy(context)) or \
                        (inspect.isclass(intf) and isinstance(context, intf)):
                    provider = factory
                    break
            else:
                provider = None

        # if provider is a callable, we call it!
        if callable(provider):
            provider = provider(context, request, view)

        if provider is None:
            provider = registry.queryMultiAdapter((context, request, view), IContentProvider,
                                                  name=name)
        if provider is not None:
            econtext['provider'] = provider
        return provider

    def get_value(arg):
        """Extract argument value from context

        Extension expression language is quite simple. Values can be given as
        positioned strings, integers or named arguments of the same types.
        """
        arg = arg.strip()
        if arg.startswith('"') or arg.startswith("'"):
            # may be a quoted string...
            return arg[1:-1]
        if '=' in arg:
            key, value = arg.split('=', 1)
            value = get_value(value)
            return {key.strip(): value}
        try:
            arg = int(arg)  # check integer value
        except ValueError:
            args = arg.split('.')
            result = econtext.get(args.pop(0))
            for arg in args:  # pylint: disable=redefined-argument-from-local
                result = getattr(result, arg)
            return result
        else:
            return arg

    def get_context_arg(arg):
        """Extract a value if present in kwargs, otherwise look into context"""
        if arg in kwargs:
            return kwargs.pop(arg)
        return econtext.get(arg)

    name = name.strip()

    args, kwargs = [], {}
    func_match = FUNCTION_EXPRESSION.match(name)
    if func_match:
        name, arguments = func_match.groups()
        for arg in map(get_value, ARGUMENTS_EXPRESSION.findall(arguments)):
            if isinstance(arg, dict):
                kwargs.update(arg)
            else:
                args.append(arg)
    else:
        match = CONTENT_PROVIDER_NAME.match(name)
        if match:
            name = match.groups()[0]
        else:
            raise ContentProviderLookupError(name)

    context = get_context_arg('context')
    request = get_context_arg('request')
    view = get_context_arg('view')

    registry = request.registry
    provider = get_provider(name)

    # raise an exception if the provider was not found.
    if provider is None:
        raise ContentProviderLookupError(name)

    # add the __name__ attribute if it implements ILocation
    if ILocation.providedBy(provider):
        provider.__name__ = name

    # Insert the data gotten from the context
    addTALNamespaceData(provider, econtext)

    # Stage 1: Do the state update
    registry.notify(BeforeUpdateEvent(provider, request))
    provider.update(*args, **kwargs)

    # Stage 2: Render the HTML content
    return provider.render()
Ejemplo n.º 8
0
 def __call__(self):
     event.notify(BeforeUpdateEvent(self.context, self.request))
     self.context.update()
     return self.context.render()