[Grok-dev] Re: first thoughts on "regebro-guido-templates"

Brandon Craig Rhodes brandon at rhodesmill.org
Tue Oct 30 09:08:44 EDT 2007


"Lennart Regebro" <regebro at gmail.com> writes:

>> Just one class would definitely be better than having to do two.
>> ... Lennart, does this look doable?
>
> Sure. Today inline templates take typically just one parameter, the
> html, while file templates take two, the filename and the prefix.
> We'd have to make the single class take all three and also make them
> keyword parameters.
>
>     def __init__(html, file=None, prefix=None):

It would be nice if people adding new templates to Grok - let's call
them "template pluggers" for short - it would be nice if template
pluggers did not have to repeat open().read() if they don't have to.
Plus, do we know for sure that all template engines want bare strings?
Might some of them want paths, or even open file objects, because they
want to decode the file themselves?  I can imagine templates that have
their own way of declaring Latin-1 vs Unicode, for example.  To handle
all three cases simply, our base class that others inherit from could
look like this (why do we redundantly call it grok.GrokPageTemplate
instead of grok.PageTemplateBase?):

    class GrokPageTemplate(...):
        def __init__(self, html=None, openfile=None, path=None):
            if html is not None:
               self.load_from_string(html, path)
            elif openfile is not None:
               self.load_from_openfile(openfile, path)
            else:
               self.load_from_path(path)

        def load_from_path(self, path):
            self.load_from_openfile(open(path), path)

        def load_from_openfile(self, openfile, path):
            self.load_from_string(openfile.read(), path)

        def load_from_string(self, html, path):
            """Override in each subclass to create the page template."""

Then the rules would be simple: if your template language always wants
to be loaded from a bare string, just override "load_from_string" and
you're done, because the infrastructure above will turn anything else
into a string for you.  But if your template language prefers to "see"
the file it's loading from, if indeed it's coming from a file - maybe
that helps it print errors better or read the file more efficiently or
whatever - then the template plugger can *also*, in addition to having
overriden "load_from_string", override either "load_from_path" or
"load_from_openfile", depending on which his template API wants.

For example, the person doing the zope.pagetemplate plugging would
want to use both plugin locations, since a PageTemplateFile is called
a bit differently than a PageTemplate.  It could look something like
this:

    class ZopePageTemplate(...):
        grok.name('pt')
        def load_from_path(self, path):
            p, f = os.path.split(path)
            self._template = zope.pagetemplatefile.PageTemplateFile(f, p)

        def load_from_string(self, html, path):
            self._template = zope.pagetemplate.PageTemplate()
            self._template.write(html)

We would, if this plan is followed through, then adjust the
"*_templates" directory scanning mechanism so that it just called
__init__ with (path=...) instead of doing the file opening and reading
itself.

I threw "path" in every call above, even though it's not strictly
necessary, because some template APIs might want the filename to print
pretty error messages with.

> I think the situation as it is now is pretty OK, but I would like to
> make one change. I would like the template namespace() to be
> responsible for both creating the default namespace, and updating it
> with view.namespace().

+1

-- 
Brandon Craig Rhodes   brandon at rhodesmill.org   http://rhodesmill.org/brandon


More information about the Grok-dev mailing list