Pythonic implementation of HAML, cross compiling to Mako template syntax.
Fetching latest commit…
Cannot retrieve the latest commit at this time.
Failed to load latest commit information.
haml Various spelling and grammar changes Aug 29, 2014
scratch Start work on more flexible node argument parsing. Mar 28, 2012
AUTHORS.txt Bump to 1.1.0 Aug 28, 2014
LICENSE.txt Include tests in distribution. Jan 20, 2012
activate Bump to 1.1.0 Aug 28, 2014

Pythonic HAML

Test Status

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. E.g.:

    - 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. E.g.:

%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. E.g.:

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

renders to:

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

Boolean Attributes

We only output the XHTML style attribute. E.g.:

%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 have function declaration/calling syntax similar to SASS-style mixins. E.g.:

    %ol - for arg in args:
        %li ${arg}

+make_ol(1, 2, 3)

renders to:



Several filters present in Haml are defined in PyHaml. These include :plain :escaped :cdata :javascript :css :sass (requires sass executable) :scss (requires sass executable) :coffeescript (requires coffee executable)

We can also take callables from the runtime globals to use as a filter, and we can also use Mako expression interpolation. E.g.:

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

Doctype: !!!

There is currently only very basic support for doctypes. In the future these commands should modify the current format of the generator to determine if it should create XML or HTML style tags (only closing when necessary, etc.).

!!! 5

renders to:

<!DOCTYPE html>

Whitespace Preservation


Haven't gotten around to these yet...