Django-like filters for Kid

0 views
Skip to first unread message

thesamet

unread,
Dec 4, 2006, 1:28:13 PM12/4/06
to TurboGears
I've thought today that it would be nice to have django-like filters in
Kid. In short,
django filters are like unix pipes - a way to chain functions. For
example,
{{ name | lower }}, or {{ identity.is_anonymous() | yes_no }}. I
personally missed the latter many times, especially due to the lack of
conditional expressions in Python<2.5.

It was fairly easy to add it to Kid (but with double-pipe, to not break
Python's syntax). I've posted in my blog a patch (for Kid), together
with some explanation:

http://www.thesamet.com/blog/2006/12/04/django-like-filters-for-kid/

If we like the idea, then maybe we can push this into Kid and Genshi.

Best,
Nadav

Christoph Zwerschke

unread,
Dec 5, 2006, 3:46:39 AM12/5/06
to turbo...@googlegroups.com
thesamet wrote:
> It was fairly easy to add it to Kid (but with double-pipe, to not break
> Python's syntax). I've posted in my blog a patch (for Kid), together
> with some explanation:

Sounds interesting; I'll have a closer look and give feedback as soon as
I find some time. Can you add a ticket for that on the Kid trac so it
will not get lost?

-- Chris

Italo Maia

unread,
Dec 5, 2006, 4:40:10 PM12/5/06
to TurboGears
Kool! I had the same though a while ago, when i was taking a look in
Django. I like the idea very much! I like it so much i took the
discution to the genshi irc channel, some guys said it would break some
stuff...don't know for sure. Maybe a new py: stuff like py:print would
make it easier to implement...

thesamet

unread,
Dec 6, 2006, 5:46:05 AM12/6/06
to TurboGears
I've updated my blog post with a patch for Genshi, and even added a few
unit tests.

Currently, 100% of Genshi's tests pass. It might break existing
templates which use || inside a ${} expression. The remedy would be to
escape || as \|\|.

I've also posted about it to the Genshi group at:
http://groups.google.com/group/genshi/browse_thread/thread/5b8b7ebb8d453bbe

Matthew Bevan

unread,
Dec 6, 2006, 2:31:45 PM12/6/06
to turbo...@googlegroups.com
Both of the examples you provide do not make sense to me...

> {{ name | lower }}, or {{ identity.is_anonymous() | yes_no }}.

name.lower() will work as long as name is a string, and you can
easily perform "tuple"-like actions with (my favorite):

identity.is_anonymous() and "Yes" or "No"

Or:

['No', 'Yes'][identity.is_anonymous()]

The KidRecipes section of their Trac (http://www.kid-templating.org/
trac/wiki/KidRecipes) features several solutions to problems that
require conditionals like that - e.g. http://www.kid-templating.org/
trac/wiki/AlternatingRowStylesRecipe

Fun doesn't enter into my code by inventing new syntax (or pulling
syntax from other languages). Fun is readable code which any Joe can
understand. What if you want to pass additional arguments to a
filter? It is no more difficult to create a library of useful
functions (which TG is slowly doing with the tg. namespace, like
tg.url) than it would be to implement filters.

Why is passing a library of useful functions inside a single
namespace (e.g. the tg. namespace) to KID or Genshi bad? Filters go
against the Zen of Python: (Yeah! I brought the Zen into the
thread! :^P )

* Explicit is better than implicit.
* Simple is better than complex.
* Special cases aren't special enough to break the rules.
* There should be one-- and preferably only one --obvious way to do it.
* Namespaces are one honking great idea -- let's do more of those!

No sir, I can't say I like it. Filters, that is. :P (Oh, and if
you want it prettier, you -can- do this:)

linebreaks( escape( story.text ))

Or, better yet, have a single function to format BBS text: (limiting
available HTML, converting BBcode to HTML, linebreaks to </p><p> and
<br/> tags as nessicary, turning links into links, etc.)

bbstext( story.text )

...or you could implement a custom subtype of unicode that implements
a render method:

story.text.render()

^_^; Implementing the sub-type is what I'd do...

Matthew Bevan, Systems Administrator
Top Floor Computer Systems Ltd.


Nadav Samet

unread,
Dec 6, 2006, 3:43:37 PM12/6/06
to turbo...@googlegroups.com
Hi Matthew,

Thanks for your comments.

Indeed, this suggestion does not add more power to Kid than it already has. It just makes its syntax nicer in many common cases.

Perhaps, it's once of the cases that practicality beats purity. IMO, expecting our users to do tricks like (["Yes", "No"][some_boolean]), or (bool and 'yes' or 'no') will turn off many newbies.

It might be a good solution indeed to pass a common set of "formatting functions" through the tg namespace. Its mostly a trade-off of purity and convenience.

Matthew Bevan

unread,
Dec 6, 2006, 4:08:22 PM12/6/06
to turbo...@googlegroups.com
Howdy!

> Thanks for your comments.

I've always wanted to play the devil's advocate. :^)

> Perhaps, it's once of the cases that practicality beats purity.
> IMO, expecting our users to do tricks like (["Yes", "No"]
> [some_boolean]), or (bool and 'yes' or 'no') will turn off many
> newbies.

No more difficult than having new users understand how a decorator
works... or a list comprehension. AFIK 'bool and trueval or
falseval' is a standard Python idiom, much like the C/C++/PHP/etc.
'bool ? trueval : falseval' statement. It, at its core, functions
the same, but also has fall-through capability (e.g. if trueval
resolves to false, say, an empty string, it will cascade to the
falseval. I think.)

As for the list index boolean - I used it for along time, before
discovering the many problems it has, specifically in the case of
using values that might not exist.

The pipe or double-pipe syntax for calling functions would be unique
to the templating engine, and users might wonder why Python doesn't
include such a feature, esp. as KID is marketed as a very Python-like
XML processor and describes ${} as "Python Expression
Substitution"... not "funky template language substitution". ;-)

> It might be a good solution indeed to pass a common set of
> "formatting functions" through the tg namespace. Its mostly a trade-
> off of purity and convenience.

Indeed, I would be much happier with this solution, and I already do
pass several formatting functions of my own. However, I'd like to
see a feature like these double-pipe filters getting past Guido to be
implemented in Python itself. XD

Have a great day,

shday

unread,
Dec 6, 2006, 10:22:15 PM12/6/06
to TurboGears
>
> name.lower() will work as long as name is a string, and you can
> easily perform "tuple"-like actions with (my favorite):
>
> identity.is_anonymous() and "Yes" or "No"
>
> Or:
>
> ['No', 'Yes'][identity.is_anonymous()]
>

In Python 2.5 we can also do:

"Yes" if identity.is_anonymous() else "No"

which is kinda neat.

thesamet

unread,
Dec 7, 2006, 4:34:32 AM12/7/06
to TurboGears
I've talked with Christopher Lenz on this, and he suggested a way to
implement it externally to the template engine parser. I've created a
package that encapsulates the filters, and can be used with both Kid
and Genshi - with no need to patch them:

http://www.thesamet.com/blog/2006/12/07/filters-01-released/

Nadav

Christoph Zwerschke

unread,
Dec 7, 2006, 8:14:03 AM12/7/06
to turbo...@googlegroups.com

Seems like the best solution. The filter syntax may be useful for some
people but I think Mathew was right that adding this to Kid or Genshi
would be contrary to their "pure Python" paradigm. The idea of
Kid/Genshi is that we don't want to learn another templating language or
sublanguage like in TAL/TALES/METAL, but simply Python so everybody who
knows Python understands what's going on.

-- Chris

Italo Maia

unread,
Dec 10, 2006, 4:36:24 PM12/10/06
to TurboGears
I loved.

Reply all
Reply to author
Forward
0 new messages