[Twisted-web] Re: Re: new nevow know-how needs...;-)

Alex Martelli twisted-web@twistedmatrix.com
Sat, 06 Mar 2004 09:07:36 +0100


James Y Knight wrote:

> On Mar 5, 2004, at 6:15 AM, Alex Martelli wrote:
>> So, won't every
>> HTML construct coming from a template of some form such as:
>>
>> <span nevow:data="bar">
>>     etc, etc
>> </span>
>>
>> end up "compiled" into a "span(data=directive('bar'))[etc, etc]"
>> anyway,
>> leading me right back into subtle issues of "WHERE is this 'bar'
>> going to be looked up, depending on phase of the moon etc"...?  Or are
>> there two different ways I should code that '<span nevow:data="bar">'
>> in
>> the on-disk template depending on whether I mean one thing or the
>> other?
> 
> Welll, it doesn't depend on the phase of the moon. directives always
> get looked up on the first data it finds above it in the tree. I'm not
> sure exactly what your question is, but, is it the lack of being able
> to go back up the tree? e.g.:

I guess, essentiallly, that's it -- except that in my experience with
the previous mechanism it appeared to me that sometimes (unpredictably)
the lookup happened on the IData set by a "SISTER" tag, rather than on
the data set by a "mother" / "grandmother" one.  If now the lookup is
always strictly "upwards" (towards the root of the tree without
exceptions), that, at least, is progress, even though I'll still have
to do lots of data fetching in renderers (mixing view and model).

Basically, assuming that's how it always works now, I have to consider 
that putting a data fetch in a data directive "poisons the well" for a 
whole subtree -- there is no "going back", ever.  If there is any
possibility at all that the templates-author (a web designer separate
from the programmer who codes the logic behind the templates) may want
to get to such other data suppliers, "hidden" by the current mechanism,
then I have to code render methods that know how to get their own
data.

> class MyPage:
>    def data_foo(context, data):
>      return {'bar':2, 'baz':3}
>    def data_other(context, data):
>      return 1
>    docFactory = xmlstr("""
>    <html>
>      <span data="foo">
>        <span data="bar" render="string">This works fine.</span>
>        <span data="other" render="string">This won't work because
> 'other' isn't a key in {'bar':2, 'baz':3}.</span>
>      </span>
>    </html>""")

Right.  calling .get("other") on that dictionary returns None,
and, that's it: the situation becomes irretrievable in the
current scheme (even though in a much clearer way than it was
in the previous one).


>> Anyway, if I understand correctly, I'll now get this "new behavior"
>> with
>> just a cvs up on the (stand-alone) Nevow CVS, which I intend to do at
>> once, so I can experiment.
> 
> Yep.

I have indeed experimented, with my adapter still in place and print
statements in said adapter to track when it's called; the number of
occurrences has dropped from many dozens to just a couple in a typical
rendering pass -- real progress, but still a LITTLE to go.


>> as "if the current IData remembrance is not adaptable to IContainer
>> [and
>> perhaps also if it is, but its .get raises?], just back off to  
>> 'external'
>> IData remembrances until a satisfactory one is found" would be
   ...
> I dont think that's the right solution. Too magical. And, what if your
> data *is* a container but you still want to get to something outside
> it? One idea that's been proposed and that makes a lot of sense to me
> is a "../" syntax, so you could say data="../other" or "/other" in the
> example above. It just hasn't been implemented yet.

It seems to me that, while a syntax to explicitly access "overridden
names" (of data suppliers) is helpful in some corner cases, the fundamental
mechanism should still be "if a name has not been overridden it's still
accessible" -- by analogy with OO programming, and also with CSS mechanics
(the latter may be more accessible to my target audience -- template authors
who are fundamentally web designers, rather than programmers).

So, basically, I'm thinking of IData remembrances as being "in a stack".

When a data directive lookup happens, it should walk up the stack, trying,
for each different IData remembrance it meets, in order, to perform:
    new_data = IContainer(said_data).get('new_name')
Instead of giving up if this raises, or binds new_data to None, such
failures, it seems to me, should just mean one keeps walking up the stack.

I don't see this as 'too magical' any more than I consider OO name lookups
(and in a single-inheritance scenario, too, the very simplest!) to be so
(CSS is more complicated and thus might be 'too magical' for some, yet
web designers are mastering THAT complicated name-lookup scenario
already...).

Guess I'll try to play with these concepts in my copious spare time and
see if I can grasp enough of the remembrance and lookup mechanisms to
implement a sandbox version of this.  Any suggestions of where to focus
in the nevow sources?


Thanks,

Alex