Breve 2.0 API changes

5 views
Skip to first unread message

Cliff Wells

unread,
Apr 9, 2008, 2:13:06 PM4/9/08
to breve-...@googlegroups.com
My work over the last few days has brought me to the realization that
Breve's primary API isn't nearly flexible enough.

Right now the process for creating and rendering templates lumps too
many things together and needlessly splits concerns. Much of this is
due to Breve trying to follow the Buffet spec. Because of the
limitations imposed by this pattern and because Buffet will likely be
deprecated by most of the frameworks at some point in the near future
(Pylons 0.9.7 and most likely TurboGears 2.0, leaving only CherryPy),
I'm going to rework the template creation process.

Here's the current pattern:

from breve import Template
from breve.tags.html import tags

vars = { }
t = Template ( tags )
t.render ( 'index', vars )

On the surface this seems fairly sane and straightforward but here's the
problem:

1) Needless separation of instantiation and render arguments. Since a
Template object can only safely be used once, there's little reason to
not pass all the arguments at instantiation time.

2) Unfortunate grouping of what should be a sequence of calls. Because
template evaluation and flattening occur within the render call, it's
not possible to get the evaluated but unflattened template (which could
be of interest if you wanted to use Tag.walk to do further processing on
it prior to flattening).

I'm still working out the details, but here's what I'm envisioning as a
replacement API:

t = Template ( 'index', tags, vars, args, kw ) # plus any other options

# at this point "t" is index.b, fully evaluated, but unflattened

def callback ( tag, is_tag ):
print tag

t.walk ( callback )

print t.render ( ) # basically just a wrapper around flatten with doctype and xml info prepended


This is the meat of the matter, but I'm sure this will cause collateral
changes in other parts of the API.

I'd be interested in hearing any feedback on this. Clearly
backwards-compatibility is a concern (hence the 2.0 version jump), but
I'm unwilling to hold back progress because of being anchored to a
limiting (and obsolete) API, so I'd rather have some other way to help
people manage version issues.

Regards,
Cliff

cbrain

unread,
Apr 10, 2008, 4:25:15 PM4/10/08
to brevé template engine
Hello Cliff,

This sounds very sensible to me. Perhaps it would also be a good idea
to be able to take some or most of the parameters for the Template
initialization from a TemplateParameters class instance or something
like that. Most of the parameters that I currently pass to the
Template initialization are the same throughout my program. Being able
to pass one argument to contains a set of default parameters for the
Template's initialization would make my (program's) life easier.

Something like:

default_breve_params = breve.template.TemplateParameters(
tags=breve.tags.html.tags,
root="/usr/www/testsite/templates",
xmlns="http://www.w3.org/1999/xhtml",
doctype='<!DOCTYPE html '
'PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" '
'"http://www.w3.org/TR/xhtml1/DTD/xhtml1-
transitional.dtd"'
'>')

# Possibility one, like your proposal:
t = Template ( 'index', tags, vars, args, kw ) # plus any other
options

# Possibility two, reusing already configured parameters:
t = default_breve_params.Template('index', vars, args, kw)

How does this sound to you?

--
Sven

cbrain

unread,
Apr 10, 2008, 5:06:26 PM4/10/08
to brevé template engine
Speaking about the TemplateParameters object, I would certainly be
very happy if that class would include the register_global() and
register_flattener() methods, so that I can have different globals and
flatteners for different kinds of templates... any thoughts about
this?

--
Sven

cbrain

unread,
Apr 10, 2008, 5:23:51 PM4/10/08
to brevé template engine
Hello Cliff,

Something that creeped into my mind while re-reading the documentation
a few minutes ago is the following: wouldn't it be possible to define
macro-like constructs in the template, that can be reused throughout
the template with custom parameters? This sounds like the "new math"
stuff that you thought up, except that this could be used outside of
repetitive constructions. It also looks like the custom render
functionality, except that the custom renderers can be defined inline
in this idea. I envision something like the following:

html [
body [
macro("menu_item", lambda params: [
li [ b [ a(href=params.url) [ params.title ] ] ]
]),
ul [
menu_item(url="test1.html", title="The first test"),
menu_item(url="test2.html", title="Another test")
],
ol [
menu_item(url="link1.html", title="Something to link to"),
menu_item(url="link2.html", title="Other nice stuff")
]
]
]

Does this make any sense to you? I would certainly like something like
this...

--
Sven




On 9 apr, 20:13, Cliff Wells <cl...@twisty-industries.com> wrote:

Cliff Wells

unread,
Apr 10, 2008, 5:51:13 PM4/10/08
to breve-...@googlegroups.com

On Thu, 2008-04-10 at 14:06 -0700, cbrain wrote:
> Speaking about the TemplateParameters object, I would certainly be
> very happy if that class would include the register_global() and
> register_flattener() methods, so that I can have different globals and
> flatteners for different kinds of templates... any thoughts about
> this?

That sounds like a good idea. Maybe the easiest way to do this is with
a class derived from Template and then just set the values as a class
attribute on the new class? All the Template class would need to do at
this point is refer to that new attribute.

Cliff

Cliff Wells

unread,
Apr 10, 2008, 6:21:05 PM4/10/08
to breve-...@googlegroups.com

On Thu, 2008-04-10 at 14:06 -0700, cbrain wrote:
> Speaking about the TemplateParameters object, I would certainly be
> very happy if that class would include the register_global() and
> register_flattener() methods, so that I can have different globals and
> flatteners for different kinds of templates... any thoughts about
> this?

Okay, so maybe a base class that looked something like this?

class TemplateSettings ( object ):
def __init__ ( self, *args, **kw ):
self.args = args
self.kw = kw

def __call__ ( self, template, vars ):
return Template ( template, vars, self.args, self.kw )


Then you could do this:

from breve import Template
from breve.tags.html import tags

template_with_defaults = TemplateSettings ( tags = tags )

myvars = { 'foo': 1 }
t = template_with_defaults ( 'index', myvars )

Cliff


Reply all
Reply to author
Forward
0 new messages