[Grok-dev] Re: regebro-guido-templates: comments

Brandon Craig Rhodes brandon at rhodesmill.org
Mon Oct 22 16:11:52 EDT 2007


Martijn Faassen <faassen at startifact.com> writes:

> Thanks for doing this work! We should give it another review and
> then merge. Is someone else volunteering to do a review?  What about
> Brandon, for instance?

I've taken a brief look already, and will take a deeper one either
tonight or tomorrow night.  My big issue at the moment is that I'm
still skeptical about whether different template languages need
different default namespaces.  It seems to me that namespace should
depend on the framekwork, not the template language.  That is: it
seems to me that if I use TurboGears, and (I'm making this up) if it
thinks of things in terms of "model", "view", and "controller", then
those ought to be the names available whether I write my templates in
Cheetah or Genshi or anything else.  Similarly, once you're in Zope 3,
then the objects beneath your template are going to be a "view", and a
"context", and a "static", etcetera - regardless of template language.
So I'm not sure yet why we would support a template language getting
to supply a different kind of default namespace.

Martijn has asked the question: how can a developer who wants to
"push" template data write code so as to be sure that nothing leaks
through because he accidentially adds to a default Zope namespace
rather than creating one from scratch?  At least two answers have been
proposed:

 1. The rule would be: "use the correct extension on your templates."
    For example, if they always used ".gr" instead of ".gt", then they
    would be running "restricted Genshi" and instead of getting their
    "view", "context", etcetera, they would only get what their own
    "view.namespace()" method defined, or, if they forgot to supply
    it, a safely empty dictionary.

 2. The rule would be: "always define namespace() methods returning
    dictionaries instead of update() methods setting attributes."  If
    a namespace method were present, then the default namespace would
    be thrown out in favor of calling the user's namespace().

>From what I understand from our brief chat, Martijn advocates the
first, whereas I advocate the second.  He seemed to say that it's easy
to check to make sure all your templates have the right extension, but
that it would be harder to write all Views with namespace() methods.
For my part, I don't see that requiring namespace() on each View is
too great a burden.

But: I'm interested in making an alternative suggestion: What if we
used adapters to solve this problem instead?

For example, what if there were an IDefaultNamespace utility type,
and The Rules were:

 a) When a View needs to build its namespace for the template, it
    calls its own .namespace() method.

 b) If the user has overriden this, then the dictionary they return is
    used as the namespace.

 c) If the user has not overriden .namespace() on their view, then the
    default grok.View.namespace() gets called, which calls for the
    IDefaultNamespace utility, __call__'s it with itself and the
    template as arguments, and then passes the result as the namespace.

 d) The default, globally-registered IDefaultNamespace builds the
    standard Zope namespace.

 e) The user can create, as a local utility on any app he pleases, the
    grok.templates.EmptyNamespace utility, which just returns an empty
    dictionary.  (Or, of course, a utility of his own devising.)

So, if the user did nothing special, then each view would be "push" or
not depending on whether he defined namespace() or not.  But, if he
declared "EmptyNamespace" to be the default namespace utility for his
app, then *all* of his views become "push" whether he supplies
namespace() or not; if he doesn't, then an empty namespace is pushed.

This way, "push"-style developers could get the safety Martijn wants
them to have, but without our being saddled with two different
extensions for every single template language just to control an
option that I think should be independent of template language to
begin with.  They would simply:

    class MyApp(grok.Application, grok.Container):
        grok.local_utility(grok.template.EmptyNamespace, IDefaultNamespace)

Anyway, these are the thoughts I'll have in my head as I review the
Genshi branch.

Besides looking at the Genshi code, what else should I be doing?
Let's list the sorts of things I should try to accomplish soon:

 - Write that Zope 3 proposal for the .adapt() method that will change
   the world.  I'm still trying to figure out what all the different
   combinations of named and un-named and local and global adapters
   are, and whether all combinations are valid, and if not, why.

 - Finish megrok.trails, which just barely works at this point, but
   only fragilely.  Are those functions available now that let you
   write pre- and post-grok actions for your classes?  They'll help me
   a lot with Trails.

 - Finish my tutorial for zalchemy.  I was waiting for the new
   zalchemy that works with SQLAlchemy 0.4 to be released, but maybe
   that won't happen soon and I should write the tutorial anyway?

 - I want to write a brief technical note for the web site about how I
   wrote my own IAuthentication for writing a CAS-enabled app, which I
   just did at work.  Twenty lines of code got my own login page
   running.

 - I should write a short technical note about how, by SSH'ing back to
   localhost with "-L 8090:localhost:8080", I can be logged in as an
   administrator using HTTP Basic Auth on :8080, then point another
   browser tab at :8090 and it not reuse the same Basic Auth password,
   so I can log in as a regular user without having to start up a new
   web browser.

 - I want to figure out, then document, how to run a Grok instance
   with only an in-RAM Data.fs for authentication bookmarks but not
   much more, for people whose real data is already in SQL.

 - I want to write a short tutorial on what to commit to Subversion so
   that your web app will work when you check it back out.  I need to
   understand first the pros and cons of Zope buildout versus just
   supplying "bootstrap.py".  The tutorial should also probably have a
   second section about backing up Data.fs, or at least pointing at
   other resources about handling Data.fs, so that it's a complete
   tutorial about storing the entire state of your app, both code and
   data.

 - I need to ask a question, which I'll do right here: In the web app
   I have written, there were two or three pieces of information that
   I turned out needing from many different views in my code.  I
   discovered that if I declared a view:

    class Common(grok.View):
        grok.context(Interface)
        def update(self):
           self.foo = 5

   then I could get the value of 'foo' from anywhere in any view by
   calling something like:

    <b tal:content="context/@@common/foo">the Foo value</b>

   Is this a valid design pattern?  Or a broken way of getting
   something that's much easier to achieve? :-)

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


More information about the Grok-dev mailing list