예제 #1
0
  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()
예제 #2
0
    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()
예제 #3
0
  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()