Pythonic way of web-programming

David Abrahams dave at boost-consulting.com
Sun Apr 20 18:00:06 EDT 2003


Ian Bicking <ianb at colorstudy.com> writes:

> On Sun, 2003-04-20 at 04:21, David Abrahams wrote:
>> I don't care much about XML programming (haven't had a use for it),
>> but at PyConDC recently I got together with a couple of guys from the
>> Twisted project who do care, and designed a nice little meta-language
>> in Python for doing this sort of template processing.  Here's a little
>> example of it in action:
>> 
>>     template = body[
>>         table(id="outer", width="100%", height="100%", border="0")[
>>             tr(valign="bottom")[
>>                 td(id="output", width="75%", valign="top", model="latestOutput")[
>>                     div(pattern="listItem", view="html")[
>>                         "Foo"
>>                     ]
>>                 ],
>>                 td(id="room-contents", valign="bottom")[
>>                     strong[
>>                         "Stuff you have"
>>                     ],
>>                     div(model="playerInventory", view="List")[
>> 
>>                         # Note programmatic elements
>>                         if_(not arg1)
>>                         [    
>>                             div(_class="item")["Nothing"]
>>                         ].else_
>
> This could almost be plain Python, if Python allowed code blocks.  

I don't understand; it already *is* plain Python.  While Donovan
Preston and I were designing the syntax, his friend Bob was sitting on
the couch coding it up.

> The use of []'s isn't really necessary, and actually the expressions
> could maybe be eval'd as well...

You've lost me here.  Lots of the "syntax" choices aren't based on
what's neccessary, but on what's clear and expressive.  As far as
"eval" is concerned, well, I'm not sure if you realize this but those
if_ and for_each elements are lazily evaluated.  The expression
creates a callable object, "template", which generates new XML.

> td(id='room-contents', valign='bottom', contents=[
>   strong(contents=['Stuff you have']),

Uh, I don't know much XML but I'd be shocked if you weren't already
allowed to have an attribute called "contents".  I'd have used
single quotes, too, but double quotes are idiomatic for XML.


>   div(model='playerInventory', view="List", contents=[
>     if_(<not arg1>, 
>         <[div(_class="item", contents=['Nothing'])]>,
>         <[for_each("i", <arg1>,
>                   <[div(style=['color: red', 'color: blue', None],
>                         view="item", controller="look", 
>                         contents=[arg1])]>)]>)])])
>
> <> is the only nice nesting braces I could think of

Yikes!  One reason I use Python is to relieve my brain from having to
read angle brackets in C++ (and X/HTml ;-)). Plus, now you have two
levels of parenthesis nesting for each sub-element.  To my eye, your
version is *way* less-manageable than what we've already done in Pure
Python.

>  (`` wouldn't really
> do, since it doesn't nest, not to mention it looks much to much like
> '').  Of course, closing that nested structure is kind of crazy.
>
> And actually <> wouldn't work, because of if <a > 10> -- it's not
> entirely ambiguous, but it certainly *looks* ambiguous.  And << and >>
> are also used, even if it's only for one of the more stupid operators. 
> Maybe <()>...
>
> It's all pipe-dreams, but code blocks sure would be nice.  I don't think
> the argument that they allow New Control Structures is correct --
> iterators and the traditional control structures actually cover
> everything I've ever thought of.  Though now that I think about it, is
> the thing above a new control structure?  A sort of inside-out control
> structure, but also asort of lazy evaluation, like a callback.

I guess you do realize it's lazy.  The thing above is just a callable
object.  Nothing fancy <wink>

> I've played around with Python objects that allow lazily evaluated
> expressions, by overloading all the comparison operators (though you
> can't overload and, or, not, or is).  In some ways it pleases me, though
> it also feels fragile -- and it's not really compatible with normal
> Python, i.e., you couldn't call a normal function with a lazy argument
> (though you could call a method on a lazy object easily enough).

I think that if you're not concerned with object identity, you can
make lazy objects fairly transparent.  Python already hands you
proxies in a few places and you hardly ever even know the difference.

-- 
Dave Abrahams
Boost Consulting
www.boost-consulting.com




More information about the Python-list mailing list