Skip to content
This repository


Subversion checkout URL

You can clone with HTTPS or Subversion.

Download ZIP

Pythonic implementation of HAML, cross compiling to Mako template syntax.

branch: master

Fetching latest commit…


Cannot retrieve the latest commit at this time

Octocat-spinner-32 examples
Octocat-spinner-32 haml
Octocat-spinner-32 scripts
Octocat-spinner-32 tests
Octocat-spinner-32 .gitignore
Octocat-spinner-32 LICENSE.txt
Octocat-spinner-32 todo.txt

Pythonic HAML

This is an implementation of HAML for Python (2.5 through 2.7).

I have kept as much of the same syntax as I could, but there are some Rubyisms built into HAML that I simply cannot replicate. I have tried to stay true to the original features while adapting them to be Pythonic.

This package essentially cross-compiles PyHAML code into a Mako template. Ergo, all of your standard Mako syntax also applies to content which does not match any of the HAML syntax.

Markup Example

A simple PyHAML template:

    #date= print_date
    #address= current_user.address

A Mako template to do the same thing:

<div id="profile">
    <div class="left column">
        <div id="date">${print_date}</div>
        <div id="address">${current_user.address}</div>
    <div class="right column">
        <div id="email">${}</div>
        <div id="bio">${}</div>

API Example

import haml
import mako.template

if your_templates_are_in_a_directory:

    # Build the template lookup.
    lookup = mako.lookup.TemplateLookup(["various", "template", "paths"],

    # Retrieve a template.
    template = lookup.get_template('example_template.haml')

else: # You have some strings...

    # Write your HAML.
    haml_source = '.content Hello, World!'

    # Build your template.
    template = mako.template.Template(haml_source,

# Render!
print template.render()


Herein lies our differences to the HAML reference.

Attributes: ()

Python syntax must be used as if calling a function that takes keyword arguments. Eg.:

    - for i in range(5):
        %li(id=['item', str(i)]) ITEM ${i}

renders to:

    <li id="item_0">ITEM 0</li>
    <li id="item_1">ITEM 1</li>
    <li id="item_2">ITEM 2</li>
    <li id="item_3">ITEM 3</li>
    <li id="item_4">ITEM 4</li>

If you want to pass in a class, use the keyword "class_". If you want to use attribute names with dashes, use camel case instead and it will be converted for you:

%meta(httpEquiv="Content-Type", content="text/html;charset=UTF-8")

renders to:

<meta http-equiv="Content-Type" content="text/html;charset=UTF-8">

If you want to pass in any other non-identifier attribute names, you can expand a mapping in place. Eg.:

%div(class_='content', **{'not-valid-python': 'value'}) content

renders to:

<div class='content', not-valid-python="value">content</div>

You can also pass in mapping objects as positional objects. Eg.:

- attrs = dict(a='one', b='two')

renders to:

<a a="one" b="two" />

Boolean Attributes

We only output the XHTML style attribute. Eg.:

%input(type='checkbox', checked=True)


<input type="checkbox" checked="checked" />

Python Evaluation: =

Running Python: -

Clearly this is now evaluating Python. It is evaluated in the Mako runtime context.

Python Interpolation: ${}

We are using Mako to do the heavy lifting here.


We don't supply any filters, but the mechanism is there to take callables from the runtime globals to use as a filter. Eg.:

-! def to_upper(x):
    return x.upper()
    %p The syntaxes, they do nothing!
    #id x
    .class x
    - statement
    / comment

Doctype: !!!

Whitespace Preservation


Haven't gotten around to these yet...

Something went wrong with that request. Please try again.