def process(self, template, params=None, localize=False): """Processes the template named or referenced by the first parameter. The optional second parameter may reference a dictionary of variable definitions. These are set before the template is processed by calling update() on the stash. Note that, unless the third parameter is true, the context is not localised and these, and any other variables set in the template will retain their new values after this method returns. The third parameter is in place so that this method can handle INCLUDE calls: the stash will be localized. # Returns the output of processing the template. Errors are raised as TemplateException objects. """ template = util.listify(unscalar(template)) params = unscalar(params) compileds = [] for name in template: compileds.append(self.template(name)) if localize: self.__stash = self.__stash.clone(params) else: self.__stash.update(params) output = cStringIO.StringIO() try: # save current component try: component = self.__stash.get("component") except: component = None for name, compiled in zip(template, compileds): if not callable(compiled): element = compiled else: element = { "name": isinstance(name, str) and name or "", "modtime": time.time() } if isinstance(component, Document): # FIXME: This block is not exercised by any test. elt = Accessor(element) elt["caller"] = component.name elt["callers"] = getattr(component, "callers", []) elt["callers"].append(component.name) self.__stash.set("component", element) if not localize: # merge any local blocks defined in the Template::Document # info our local BLOCKS cache if isinstance(compiled, Document): tblocks = compiled.blocks() if tblocks: self.__blocks.update(tblocks) if callable(compiled): tmpout = compiled(self) elif util.can(compiled, "process"): tmpout = compiled.process(self) else: self.throw("file", "invalid template reference: %s" % compiled) if self.__trim: tmpout = tmpout.strip() output.write(tmpout) # pop last item from callers if isinstance(component, Document): elt["callers"].pop() self.__stash.set("component", component) finally: if localize: # ensure stash is delocalised before dying self.__stash = self.__stash.declone() return output.getvalue()
def print_(self, *args): """Prints @items in turn by mapping each to an approriate template using the internal 'map' dictionary. If an entry isn't found and the item is an object that implements the method named in the internal 'method' item, (default: 'present'), then the method will be called passing a reference to 'self', against which the presenter method may make callbacks (e.g. to view_item()). If the presenter method isn't implemented, then the 'default' map entry is consulted and used if defined. The final argument may be a dictionary providing local overrides to the internal defaults for various items (prefix, suffix, etc). In the presence of this parameter, a clone of the current object is first made, applying any configuration updates, and control is then delegated to it. """ args = list(args) if len(args) > 1 and isinstance(args[-1], dict): cfg = args.pop() clone = self.clone(cfg) return clone.print_(*args) output = StringIO() for item in args: if isinstance(item, (tuple, list)): type = "ARRAY" elif isinstance(item, dict): type = "HASH" elif isinstance(item, (str, int)): type = "TEXT" else: type = item.__class__.__name__ template = self._map.get(type) if template is None: # No specific map entry for object, maybe it implements a # 'present' (or other) method? # Hack: Have to explicitly disallow View objects, since # our promiscuous __getattr__ method will dynamically create # a getter/setter subroutine for most any method name. # Perl's UNIVERSAL::can method ignores AUTOLOAD, but # Python's getattr() does not ignore __getattr__. if not isinstance(item, View) and can(item, self._method): output.write(str(getattr(item, self._method)(self))) continue done = False newtype = None if isinstance(item, dict): newtype = item.get(self._method) if newtype is not None: template = self._map.get("%s=>%s" % (self._method, newtype)) done = template is not None if not done and newtype is not None: template = self._map.get("%s=>*" % (self._method, )) if template is not None: template = template.replace("*", newtype) done = True if not done: template = self._map.get("default") or type if template: output.write(str(self.view(template, item))) return output.getvalue()
def print_(self, *args): """Prints @items in turn by mapping each to an approriate template using the internal 'map' dictionary. If an entry isn't found and the item is an object that implements the method named in the internal 'method' item, (default: 'present'), then the method will be called passing a reference to 'self', against which the presenter method may make callbacks (e.g. to view_item()). If the presenter method isn't implemented, then the 'default' map entry is consulted and used if defined. The final argument may be a dictionary providing local overrides to the internal defaults for various items (prefix, suffix, etc). In the presence of this parameter, a clone of the current object is first made, applying any configuration updates, and control is then delegated to it. """ args = list(args) if len(args) > 1 and isinstance(args[-1], dict): cfg = args.pop() clone = self.clone(cfg) return clone.print_(*args) output = cStringIO.StringIO() for item in args: if isinstance(item, (tuple, list)): type = "ARRAY" elif isinstance(item, dict): type = "HASH" elif isinstance(item, (basestring, int, long)): type = "TEXT" else: type = item.__class__.__name__ template = self._map.get(type) if template is None: # No specific map entry for object, maybe it implements a # 'present' (or other) method? # Hack: Have to explicitly disallow View objects, since # our promiscuous __getattr__ method will dynamically create # a getter/setter subroutine for most any method name. # Perl's UNIVERSAL::can method ignores AUTOLOAD, but # Python's getattr() does not ignore __getattr__. if not isinstance(item, View) and can(item, self._method): output.write(str(getattr(item, self._method)(self))) continue done = False newtype = None if isinstance(item, dict): newtype = item.get(self._method) if newtype is not None: template = self._map.get("%s=>%s" % (self._method, newtype)) done = template is not None if not done and newtype is not None: template = self._map.get("%s=>*" % (self._method,)) if template is not None: template = template.replace("*", newtype) done = True if not done: template = self._map.get("default") or type if template: output.write(str(self.view(template, item))) return output.getvalue()