Filters 0.1 Released

Filters is a Python package that provides shell-like data processing operators for generation of web content. Filters is designed to work together with a template-engine like Kid and Genshi.

What is a filter?

We’ll start with an example.

${ identity.is_anonymous() | tg.yesno() }


The output of this will be the value returned by is_anonymous() after being processed by the yesno filter, which translates a boolean to either “yes” or “no”.

Some filters can do really cool stuff. For instance, consider this:

  • {{ file_size | tg.filesizeformat() }}: this would print the size in a human-readable format (i.e. 17 KB, 102.4MB and so on).
  • {{ story.text | tg.escape() | tg.linebreaks() }}: this will escape all ampersands from the text and then convert all newlines to <p> and <br/>. This also demonstrates that filters can be chained.
  • You have {{egg_count}} egg{{egg_count | tg.pluralize()}} left: will pluralize the egg noun with the suffix ’s’ if egg_count is not one.

The main goal of Filters is to provide a rich set of easy-to-use operations that are commonly needed in real-world applications.

After implementing this in a form of patches for Kid and Genshi, Christopher Lenz from Genshi suggested a way to implement this externally to the parsers. The idea is based on this recipe from the Python Cookbook. This solution enjoys the benefits of using pure Python syntax. This means that we are now using single bar (|) again.

Here’s how to use it.

Download and install

Get this: Filters-0.1.tar.gz. Extract the archive and run python setup.py install.

Hook into TurboGears

Go to controllers.py, add add the following lines:

from filters.core import tg_add_variables
tg_add_variables()

If you’d like to have the filters under their own namespace, replace the last line by:

tg_add_variables(pollute=False)


And the filters will be available under tg.filters instead of under tg.

Using filters

Here are some examples demonstrating how to use filters:

${ identity.is_anonymous() | tg.yesno() }

You have ${count} cherr${count | tg.pluralize('y,ies') }.

Note that filters accept their argument in parenthesis. The paranthesis are required even if there are no arguments.

Writing your own filters

Basically, a filter is just a function that takes input and possibly some arguments, and returns an output, that will
be passed to the next filter, or to the output. The Filters package provide two decorators to help you with filters. The first is make_filter that transforms your function to a filter class, and the second is register_filter which registers your filter and makes it available inside templates. Here’s how to use it:

from filters.core import register_filter, make_filter

@register_filter()
@make_filter()
def shorturl(input, max_length=50):
    return input.split('?')[0][:max_length]

Then, inside your template:

${ my_url | tg.shorturl() }

or

${ my_url | tg.shorturl(25) }

Good luck, and feel free to leave here questions or comments.

This entry was posted in Filters, turbogears. Bookmark the permalink.

6 Responses to Filters 0.1 Released

  1. Pingback: Django-like filters for Kid (and Genshi) | Nadav Samet’s Blog

  2. alastair says:

    Why have two decorators rather than one? Aren’t we always going to write both of them?

    Put another way, is there a use for writing just one of the decorators and not the other?

  3. thesamet says:

    Alastir, you could be right. It makes sense to add a convenience decorator that does both.

  4. Italo Maia says:

    Adorei!

    Loved!

  5. Ben Bangert says:

    Myghty has had filters since its inception as well, which essentially just need to take an argument and return. The function style for a filter seems universal enough that there’s little reason I can see for filters to be bound to a specific template language.

    Of course, I’m somewhat curious when one would decide that something should be used as a filter vs a normal function call. In Django for example, they *have* to use filters for a lot of those since they can’t just call Python functions (the template language won’t allow normal function calls).

    So what they would have to write as {{ file_size | tg.filesizeformat() }} you could write in Kid as ${ tg.filesizeformat(file_size)}. If you have something you need to format 3 times, it definitely makes more sense to use a filter style than wrapping all those functions. Maybe someone else has some good set of guidelines for when you’d use one instead of the other?

  6. Nice post. I was checking continuously this blog and I am impressed!
    Very helpful info specially the last part :) I care for
    such information much. I was seeking this particular info
    for a long time. Thank you and best of luck.

Leave a Reply

Your email address will not be published. Required fields are marked *

You may use these HTML tags and attributes: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <strike> <strong>