Re: Breve improvement (?)

28 views
Skip to first unread message

Cliff Wells

unread,
Aug 18, 2010, 12:38:41 AM8/18/10
to ma...@keveney.com, breve-...@googlegroups.com
On Tue, 2010-08-17 at 20:41 -0700, Matt Keveney wrote:
> Cliff,
>
> Please let me know if this discussion would be better moved to a public
> forum; the Google groups activity seems to have stalled some time ago, so I thought I'd email you directly.

The google group is um... slow <wink>, but still, keeping it in the
public is how it stays alive, so I'm cc'ing the list.

> I'm fairly new to Python, but have been writing code for over 20 years,
> most recently using Ruby and a templating DSL called 'Erector.' I was
> looking for a similar DSL approach to templates for Python, and am very
> impressed with Breve. Nice!
>
> My first exercise was to convert a Google App Engine example to Breve. The
> example iterates over a list of objects which are mapped to rows in their
> database engine.
>
> http://code.google.com/appengine/docs/python/gettingstarted/usingdatastore.html
>
> I successfully converted it to the 'list comprehension' form without
> difficulty, but I'd prefer to use the 'tag multiplication' technique.
> Unfortunately this fails, since the list items are objects instead of
> dictionaries.
>
> I found the code in the 'tags' module which implements the multiply
> operator. I think what I want is an alternative to the 'Template'
> class
> which accepts objects _or_ dictionaries and does the right thing.

The Template class is a bit hairy and not really the right place to
start anyway.

While you could force your way through tag multiplication, I think the
right solution looks more like this:


from breve.tags.html import tags as T
from breve.flatten import flatten

# couple of phony classes to test with
class Author (object):
def __init__ (self, nickname):
self._nick = nickname
def nickname (self):
return self._nick

class Greeting (object):
def __init__ (self, nickname, content):
self.author = Author(nickname)
self.content = content

# some phony data for our phony classes
greetings = [
Greeting ('joe', 'hola'),
Greeting ('ed', 'yo'),
Greeting ('bob', 'hello')
]


def greeting_fragment (greeting):
return (
T.b [ greeting.author.nickname () ] if greeting.author else 'An anonymous person wrote:',
T.blockquote [ greeting.content ]
)


print flatten (
T.html [
T.body [
[ greeting_fragment (g) for g in greetings ]
]
]
)


I'm still using a listcomp, but it's very, very simple, so tag
multiplication buys you nothing. I think the key bit here is that you
have to keep in mind is that one of the goals of Breve is to move easily
between template and code, so you can mix template fragments into your
program and pass functions into templates without it feeling unnatural.

If you still want to use tag multiplication, then what you'll want to
look at is not Template, but rather:

http://github.com/cwells/breve/blob/master/breve/tags/__init__.py

There you'll find the __mul__ method of the Tag class which is where
this is implemented. I'm sure you could probably do some magic to
determine if you're getting a list of dicts or a list of objects (and
keep in mind that Python objects are basically implemented as dicts, so
you've got a foot up) and achieve what you're asking for.

That being said, I'm not convinced it's worth the effort, and I suspect
you'll be creating more corner cases than anyone would be comfortable
with (think composite classes).

> If I can get it going, I'll fork it on Github and let you know, if
> that's
> okay with you.

That's fine with me. If your changes are compatible with the overall
goals of Breve then I'd be happy to accept patches.

Regards,
Cliff


Cliff Wells

unread,
Aug 18, 2010, 1:05:53 AM8/18/10
to breve-...@googlegroups.com, ma...@keveney.com
On Tue, 2010-08-17 at 21:38 -0700, Cliff Wells wrote:

> def greeting_fragment (greeting):
> return (
> T.b [ greeting.author.nickname () ] if greeting.author else 'An anonymous person wrote:',
> T.blockquote [ greeting.content ]
> )
>
>
> print flatten (
> T.html [
> T.body [
> [ greeting_fragment (g) for g in greetings ]
> ]
> ]
> )

I should also point out that you can utilize register_global to make
your function available to all your templates without having to pass it
in your variables:

import breve
breve.register_global ('greeting_fragment', greeting_fragment)

see http://breve.twisty-industries.com/documentation#the-breve-api

where it is somewhat tersely documented.

Regards,
Cliff


mattk

unread,
Aug 19, 2010, 2:32:39 AM8/19/10
to brevé template engine
Thanks for the feedback and pointers.

I'm still experimenting with various ways to use Breve, and haven't
yet settled on a particular pattern. If I return to the tag
multiplication technique, I'll updated this thread with my progress.

Still liking Breve, after two days of use. That's a personal record
for an html template solution!

-Matt

cwells

unread,
Aug 19, 2010, 3:03:26 AM8/19/10
to brevé template engine
Glad to hear you're liking it! It does take a while to find a
pattern (I'm saying that as the primary author and longest user of
Breve). Prior to Breve I tried Stan from Twisted/Nevow and
completely did not get it. It didn't dawn on me until many months
later how I'd completely missed the point.

I think the guide I rely on most is simply this: if I'm trying to
accomplish some task in Breve and it seems overly awkward, I consider
writing it as a Python function and passing it to Breve. If the
function can be made reusable, even better. If the function will
need to generate HTML, then I simply use Breve tags within the
function.
In fact, I should point out that the concept of a "template" is a bit
tacked onto Breve, mostly to satisfy the separation of concerns in MVC
style frameworks. In reality, you could just as easily have a
Python module be a "template" (in fact, this was a design decision I
debated early-on in the development of Breve). I guess my point is
simply that Breve is a DSL, and DSL's are meant to be mixed freely
with regular code, so don't be afraid to do so. It's something the
Lisp folks learned long ago and the rest of us are still resisting =)

Anyway, good luck! Feel free to bother me as much as needed.
Reply all
Reply to author
Forward
0 new messages