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()
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()
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()
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
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()
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()
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()
def __call__(self): event.notify(BeforeUpdateEvent(self.context, self.request)) self.context.update() return self.context.render()