You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@ambari.apache.org by ao...@apache.org on 2014/09/03 20:19:57 UTC

[12/22] AMBARI-7138. Ambari RPM deals with jinja2 dependency incorrectly (aonishuk)

http://git-wip-us.apache.org/repos/asf/ambari/blob/7c3ea59f/ambari-common/src/main/python/ambari_jinja2/examples/bench.py
----------------------------------------------------------------------
diff --git a/ambari-common/src/main/python/ambari_jinja2/examples/bench.py b/ambari-common/src/main/python/ambari_jinja2/examples/bench.py
new file mode 100644
index 0000000..0f4f982
--- /dev/null
+++ b/ambari-common/src/main/python/ambari_jinja2/examples/bench.py
@@ -0,0 +1,433 @@
+"""\
+    This benchmark compares some python templating engines with Jinja 2 so
+    that we get a picture of how fast Jinja 2 is for a semi real world
+    template.  If a template engine is not installed the test is skipped.\
+"""
+import sys
+import cgi
+from timeit import Timer
+from ambari_jinja2 import Environment as JinjaEnvironment
+
+context = {
+    'page_title': 'mitsuhiko\'s benchmark',
+    'table': [dict(a=1,b=2,c=3,d=4,e=5,f=6,g=7,h=8,i=9,j=10) for x in range(1000)]
+}
+
+jinja_template = JinjaEnvironment(
+    line_statement_prefix='%',
+    variable_start_string="${",
+    variable_end_string="}"
+).from_string("""\
+<!doctype html>
+<html>
+  <head>
+    <title>${page_title|e}</title>
+  </head>
+  <body>
+    <div class="header">
+      <h1>${page_title|e}</h1>
+    </div>
+    <ul class="navigation">
+    % for href, caption in [
+        ('index.html', 'Index'),
+        ('downloads.html', 'Downloads'),
+        ('products.html', 'Products')
+      ]
+      <li><a href="${href|e}">${caption|e}</a></li>
+    % endfor
+    </ul>
+    <div class="table">
+      <table>
+      % for row in table
+        <tr>
+        % for cell in row
+          <td>${cell}</td>
+        % endfor
+        </tr>
+      % endfor
+      </table>
+    </div>
+  </body>
+</html>\
+""")
+
+def test_jinja():
+    jinja_template.render(context)
+
+try:
+    from tornado.template import Template
+except ImportError:
+    test_tornado = None
+else:
+    tornado_template = Template("""\
+<!doctype html>
+<html>
+  <head>
+    <title>{{ page_title }}</title>
+  </head>
+  <body>
+    <div class="header">
+      <h1>{{ page_title }}</h1>
+    </div>
+    <ul class="navigation">
+    {% for href, caption in [ \
+        ('index.html', 'Index'), \
+        ('downloads.html', 'Downloads'), \
+        ('products.html', 'Products') \
+      ] %}
+      <li><a href="{{ href }}">{{ caption }}</a></li>
+    {% end %}
+    </ul>
+    <div class="table">
+      <table>
+      {% for row in table %}
+        <tr>
+        {% for cell in row %}
+          <td>{{ cell }}</td>
+        {% end %}
+        </tr>
+      {% end %}
+      </table>
+    </div>
+  </body>
+</html>\
+""")
+
+    def test_tornado():
+        tornado_template.generate(**context)
+
+try:
+    from django.conf import settings
+    settings.configure()
+    from django.template import Template as DjangoTemplate, Context as DjangoContext
+except ImportError:
+    test_django = None
+else:
+    django_template = DjangoTemplate("""\
+<!doctype html>
+<html>
+  <head>
+    <title>{{ page_title }}</title>
+  </head>
+  <body>
+    <div class="header">
+      <h1>{{ page_title }}</h1>
+    </div>
+    <ul class="navigation">
+    {% for href, caption in navigation %}
+      <li><a href="{{ href }}">{{ caption }}</a></li>
+    {% endfor %}
+    </ul>
+    <div class="table">
+      <table>
+      {% for row in table %}
+        <tr>
+        {% for cell in row %}
+          <td>{{ cell }}</td>
+        {% endfor %}
+        </tr>
+      {% endfor %}
+      </table>
+    </div>
+  </body>
+</html>\
+""")
+
+    def test_django():
+        c = DjangoContext(context)
+        c['navigation'] = [('index.html', 'Index'), ('downloads.html', 'Downloads'),
+                           ('products.html', 'Products')]
+        django_template.render(c)
+
+try:
+    from mako.template import Template as MakoTemplate
+except ImportError:
+    test_mako = None
+else:
+    mako_template = MakoTemplate("""\
+<!doctype html>
+<html>
+  <head>
+    <title>${page_title|h}</title>
+  </head>
+  <body>
+    <div class="header">
+      <h1>${page_title|h}</h1>
+    </div>
+    <ul class="navigation">
+    % for href, caption in [('index.html', 'Index'), ('downloads.html', 'Downloads'), ('products.html', 'Products')]:
+      <li><a href="${href|h}">${caption|h}</a></li>
+    % endfor
+    </ul>
+    <div class="table">
+      <table>
+      % for row in table:
+        <tr>
+        % for cell in row:
+          <td>${cell}</td>
+        % endfor
+        </tr>
+      % endfor
+      </table>
+    </div>
+  </body>
+</html>\
+""")
+
+    def test_mako():
+        mako_template.render(**context)
+
+try:
+    from genshi.template import MarkupTemplate as GenshiTemplate
+except ImportError:
+    test_genshi = None
+else:
+    genshi_template = GenshiTemplate("""\
+<html xmlns="http://www.w3.org/1999/xhtml" xmlns:py="http://genshi.edgewall.org/">
+  <head>
+    <title>${page_title}</title>
+  </head>
+  <body>
+    <div class="header">
+      <h1>${page_title}</h1>
+    </div>
+    <ul class="navigation">
+      <li py:for="href, caption in [
+        ('index.html', 'Index'),
+        ('downloads.html', 'Downloads'),
+        ('products.html', 'Products')]"><a href="${href}">${caption}</a></li>
+    </ul>
+    <div class="table">
+      <table>
+        <tr py:for="row in table">
+          <td py:for="cell in row">${cell}</td>
+        </tr>
+      </table>
+    </div>
+  </body>
+</html>\
+""")
+
+    def test_genshi():
+        genshi_template.generate(**context).render('html', strip_whitespace=False)
+
+try:
+    from Cheetah.Template import Template as CheetahTemplate
+except ImportError:
+    test_cheetah = None
+else:
+    cheetah_template = CheetahTemplate("""\
+#import cgi
+<!doctype html>
+<html>
+  <head>
+    <title>$cgi.escape($page_title)</title>
+  </head>
+  <body>
+    <div class="header">
+      <h1>$cgi.escape($page_title)</h1>
+    </div>
+    <ul class="navigation">
+    #for $href, $caption in [('index.html', 'Index'), ('downloads.html', 'Downloads'), ('products.html', 'Products')]:
+      <li><a href="$cgi.escape($href)">$cgi.escape($caption)</a></li>
+    #end for
+    </ul>
+    <div class="table">
+      <table>
+      #for $row in $table:
+        <tr>
+        #for $cell in $row:
+          <td>$cell</td>
+        #end for
+        </tr>
+      #end for
+      </table>
+    </div>
+  </body>
+</html>\
+""", searchList=[dict(context)])
+
+    def test_cheetah():
+        unicode(cheetah_template)
+
+try:
+    import tenjin
+except ImportError:
+    test_tenjin = None
+else:
+    tenjin_template = tenjin.Template()
+    tenjin_template.convert("""\
+<!doctype html>
+<html>
+  <head>
+    <title>${page_title}</title>
+  </head>
+  <body>
+    <div class="header">
+      <h1>${page_title}</h1>
+    </div>
+    <ul class="navigation">
+<?py for href, caption in [('index.html', 'Index'), ('downloads.html', 'Downloads'), ('products.html', 'Products')]: ?>
+      <li><a href="${href}">${caption}</a></li>
+<?py #end ?>
+    </ul>
+    <div class="table">
+      <table>
+<?py for row in table: ?>
+        <tr>
+<?py     for cell in row: ?>
+          <td>#{cell}</td>
+<?py #end ?>
+        </tr>
+<?py #end ?>
+      </table>
+    </div>
+  </body>
+</html>\
+""")
+
+    def test_tenjin():
+        from tenjin.helpers import escape, to_str
+        tenjin_template.render(context, locals())
+
+try:
+    from spitfire.compiler import util as SpitfireTemplate
+    from spitfire.compiler.analyzer import o2_options as spitfire_optimizer
+except ImportError:
+    test_spitfire = None
+else:
+    spitfire_template = SpitfireTemplate.load_template("""\
+<!doctype html>
+<html>
+  <head>
+    <title>$cgi.escape($page_title)</title>
+  </head>
+  <body>
+    <div class="header">
+      <h1>$cgi.escape($page_title)</h1>
+    </div>
+    <ul class="navigation">
+    #for $href, $caption in [('index.html', 'Index'), ('downloads.html', 'Downloads'), ('products.html', 'Products')]
+      <li><a href="$cgi.escape($href)">$cgi.escape($caption)</a></li>
+    #end for
+    </ul>
+    <div class="table">
+      <table>
+      #for $row in $table
+        <tr>
+        #for $cell in $row
+          <td>$cell</td>
+        #end for
+        </tr>
+      #end for
+      </table>
+    </div>
+  </body>
+</html>\
+""", 'spitfire_tmpl', spitfire_optimizer, {'enable_filters': False})
+    spitfire_context = dict(context, **{'cgi': cgi})
+
+    def test_spitfire():
+        spitfire_template(search_list=[spitfire_context]).main()
+
+
+try:
+    from chameleon.zpt.template import PageTemplate
+except ImportError:
+    test_chameleon = None
+else:
+    chameleon_template = PageTemplate("""\
+<html xmlns:tal="http://xml.zope.org/namespaces/tal">
+  <head>
+    <title tal:content="page_title">Page Title</title>
+  </head>
+  <body>
+    <div class="header">
+      <h1 tal:content="page_title">Page Title</h1>
+    </div>
+    <ul class="navigation">
+    <li tal:repeat="item sections"><a tal:attributes="href item[0]" tal:content="item[1]">caption</a></li>
+    </ul>
+    <div class="table">
+      <table>
+        <tr tal:repeat="row table">
+        <td tal:repeat="cell row" tal:content="row[cell]">cell</td>
+        </tr>
+      </table>
+    </div>
+  </body>
+</html>\
+""")
+    chameleon_context = dict(context)
+    chameleon_context['sections'] = [
+        ('index.html', 'Index'),
+        ('downloads.html', 'Downloads'),
+        ('products.html', 'Products')
+    ]
+    def test_chameleon():
+        chameleon_template.render(**chameleon_context)
+
+try:
+    from chameleon.zpt.template import PageTemplate
+    from chameleon.genshi import language
+except ImportError:
+    test_chameleon_genshi = None
+else:
+    chameleon_genshi_template = PageTemplate("""\
+<html xmlns="http://www.w3.org/1999/xhtml" xmlns:py="http://genshi.edgewall.org/">
+  <head>
+    <title>${page_title}</title>
+  </head>
+  <body>
+    <div class="header">
+      <h1>${page_title}</h1>
+    </div>
+    <ul class="navigation">
+    <li py:for="info in sections"><a href="${info[0]}">${info[1]}</a></li>
+    </ul>
+    <div class="table">
+      <table>
+        <tr py:for="row in table">
+          <td py:for="cell in row">${row[cell]}</td>
+        </tr>
+      </table>
+    </div>
+  </body>
+</html>\
+""", parser=language.Parser())
+    chameleon_genshi_context = dict(context)
+    chameleon_genshi_context['sections'] = [
+        ('index.html', 'Index'),
+        ('downloads.html', 'Downloads'),
+        ('products.html', 'Products')
+    ]
+    def test_chameleon_genshi():
+        chameleon_genshi_template.render(**chameleon_genshi_context)
+
+
+sys.stdout.write('\r' + '\n'.join((
+    '=' * 80,
+    'Template Engine BigTable Benchmark'.center(80),
+    '=' * 80,
+    __doc__,
+    '-' * 80
+)) + '\n')
+
+
+for test in 'jinja', 'mako', 'tornado', 'tenjin', 'spitfire', 'django', 'genshi', 'cheetah', 'chameleon', 'chameleon_genshi':
+    if locals()['test_' + test] is None:
+        sys.stdout.write('    %-20s*not installed*\n' % test)
+        continue
+    t = Timer(setup='from __main__ import test_%s as bench' % test,
+              stmt='bench()')
+    sys.stdout.write(' >> %-20s<running>' % test)
+    sys.stdout.flush()
+    sys.stdout.write('\r    %-20s%.4f seconds\n' % (test, t.timeit(number=50) / 50))
+sys.stdout.write('-' * 80 + '\n')
+sys.stdout.write('''\
+    WARNING: The results of this benchmark are useless to compare the
+    performance of template engines and should not be taken seriously in any
+    way.  It's testing the performance of simple loops and has no real-world
+    usefulnes.  It only used to check if changes on the Jinja code affect
+    performance in a good or bad way and how it roughly compares to others.
+''' + '=' * 80 + '\n')

http://git-wip-us.apache.org/repos/asf/ambari/blob/7c3ea59f/ambari-common/src/main/python/ambari_jinja2/examples/profile.py
----------------------------------------------------------------------
diff --git a/ambari-common/src/main/python/ambari_jinja2/examples/profile.py b/ambari-common/src/main/python/ambari_jinja2/examples/profile.py
new file mode 100644
index 0000000..33de2a0
--- /dev/null
+++ b/ambari-common/src/main/python/ambari_jinja2/examples/profile.py
@@ -0,0 +1,52 @@
+try:
+    from cProfile import Profile
+except ImportError:
+    from profile import Profile
+from pstats import Stats
+from ambari_jinja2 import Environment as JinjaEnvironment
+
+context = {
+    'page_title': 'mitsuhiko\'s benchmark',
+    'table': [dict(a=1,b=2,c=3,d=4,e=5,f=6,g=7,h=8,i=9,j=10) for x in range(1000)]
+}
+
+source = """\
+% macro testmacro(x)
+  <span>${x}</span>
+% endmacro
+<!doctype html>
+<html>
+  <head>
+    <title>${page_title|e}</title>
+  </head>
+  <body>
+    <div class="header">
+      <h1>${page_title|e}</h1>
+    </div>
+    <div class="table">
+      <table>
+      % for row in table
+        <tr>
+        % for cell in row
+          <td>${testmacro(cell)}</td>
+        % endfor
+        </tr>
+      % endfor
+      </table>
+    </div>
+  </body>
+</html>\
+"""
+jinja_template = JinjaEnvironment(
+    line_statement_prefix='%',
+    variable_start_string="${",
+    variable_end_string="}"
+).from_string(source)
+print jinja_template.environment.compile(source, raw=True)
+
+
+p = Profile()
+p.runcall(lambda: jinja_template.render(context))
+stats = Stats(p)
+stats.sort_stats('time', 'calls')
+stats.print_stats()

http://git-wip-us.apache.org/repos/asf/ambari/blob/7c3ea59f/ambari-common/src/main/python/ambari_jinja2/examples/rwbench/django/_form.html
----------------------------------------------------------------------
diff --git a/ambari-common/src/main/python/ambari_jinja2/examples/rwbench/django/_form.html b/ambari-common/src/main/python/ambari_jinja2/examples/rwbench/django/_form.html
new file mode 100644
index 0000000..9c4f710
--- /dev/null
+++ b/ambari-common/src/main/python/ambari_jinja2/examples/rwbench/django/_form.html
@@ -0,0 +1 @@
+<form action="{{ action }}" method="{{ method }}">{{ body }}</form>

http://git-wip-us.apache.org/repos/asf/ambari/blob/7c3ea59f/ambari-common/src/main/python/ambari_jinja2/examples/rwbench/django/_input_field.html
----------------------------------------------------------------------
diff --git a/ambari-common/src/main/python/ambari_jinja2/examples/rwbench/django/_input_field.html b/ambari-common/src/main/python/ambari_jinja2/examples/rwbench/django/_input_field.html
new file mode 100644
index 0000000..290fdbd
--- /dev/null
+++ b/ambari-common/src/main/python/ambari_jinja2/examples/rwbench/django/_input_field.html
@@ -0,0 +1 @@
+<input type="{{ type }}" value="{{ value }}" name="{{ name }}">

http://git-wip-us.apache.org/repos/asf/ambari/blob/7c3ea59f/ambari-common/src/main/python/ambari_jinja2/examples/rwbench/django/_textarea.html
----------------------------------------------------------------------
diff --git a/ambari-common/src/main/python/ambari_jinja2/examples/rwbench/django/_textarea.html b/ambari-common/src/main/python/ambari_jinja2/examples/rwbench/django/_textarea.html
new file mode 100644
index 0000000..7f10424
--- /dev/null
+++ b/ambari-common/src/main/python/ambari_jinja2/examples/rwbench/django/_textarea.html
@@ -0,0 +1 @@
+<textarea name="{{ name }}" rows="{{ rows }}" cols="{{ cols }}">{{ value }}</textarea>

http://git-wip-us.apache.org/repos/asf/ambari/blob/7c3ea59f/ambari-common/src/main/python/ambari_jinja2/examples/rwbench/django/index.html
----------------------------------------------------------------------
diff --git a/ambari-common/src/main/python/ambari_jinja2/examples/rwbench/django/index.html b/ambari-common/src/main/python/ambari_jinja2/examples/rwbench/django/index.html
new file mode 100644
index 0000000..6f620bb
--- /dev/null
+++ b/ambari-common/src/main/python/ambari_jinja2/examples/rwbench/django/index.html
@@ -0,0 +1,29 @@
+{% extends "layout.html" %}
+{% block page_title %}Index Page{% endblock %}
+{% block body %}
+  {% for article in articles %}
+  {% if article.published %}
+  <div class="article">
+    <h2><a href="{{ article.href }}">{{ article.title }}</a></h2>
+    <p class="meta">written by <a href="{{ article.user.href }}">{{ article.user.username }}</a> on {{ article.pub_date|dateformat }}</p>
+    <div class="text">{{ article.body|safe }}</div>
+  </div>
+  {% endif %}
+  {% endfor %}
+  {% form %}
+    <dl>
+      <dt>Name</dt>
+      <dd>{% input_field 'name' %}</dd>
+      <dt>E-Mail</dt>
+      <dd>{% input_field 'email' %}</dd>
+      <dt>URL</dt>
+      <dd>{% input_field 'url' %}</dd>
+      <dt>Comment</dt>
+      <dd>{% textarea 'comment' %}</dd>
+      <dt>Captcha</dt>
+      <dd>{% input_field 'captcha' %}</dd>
+    </dl>
+    {% input_field '' 'submit' 'Submit' %}
+    {% input_field 'cancel' 'submit' 'Cancel' %}
+  {% endform %}
+{% endblock %}

http://git-wip-us.apache.org/repos/asf/ambari/blob/7c3ea59f/ambari-common/src/main/python/ambari_jinja2/examples/rwbench/django/layout.html
----------------------------------------------------------------------
diff --git a/ambari-common/src/main/python/ambari_jinja2/examples/rwbench/django/layout.html b/ambari-common/src/main/python/ambari_jinja2/examples/rwbench/django/layout.html
new file mode 100644
index 0000000..60039ce
--- /dev/null
+++ b/ambari-common/src/main/python/ambari_jinja2/examples/rwbench/django/layout.html
@@ -0,0 +1,29 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN" "http://www.w3.org/TR/html4/strict.dtd">
+<html>
+<head>
+  <title>{% block page_title %}{% endblock %} | RealWorld Benchmark</title>
+  <meta http-equiv="Content-Type" content="text/html; charset=utf-8">
+</head>
+<body>
+  <div class="contents">
+    <div class="header">
+      <h1>RealWorld Benchmark</h1>
+      <blockquote><p>
+        A less stupid benchmark for Mako and Jinja2 to get an impression how
+        code changes affect runtime performance.
+      </p></blockquote>
+    </div>
+    <ul class="navigation">
+    {% for href, caption in page_navigation %}
+      <li><a href="{{ href }}">{{ caption }}</a></li>
+    {% endfor %}
+    </ul>
+    <div class="body">
+      {% block body %}{% endblock %}
+    </div>
+    <div class="footer">
+      &copy; Copyright 2008 by I don't know who.
+    </div>
+  </div>
+</body>
+</html>

http://git-wip-us.apache.org/repos/asf/ambari/blob/7c3ea59f/ambari-common/src/main/python/ambari_jinja2/examples/rwbench/djangoext.py
----------------------------------------------------------------------
diff --git a/ambari-common/src/main/python/ambari_jinja2/examples/rwbench/djangoext.py b/ambari-common/src/main/python/ambari_jinja2/examples/rwbench/djangoext.py
new file mode 100644
index 0000000..9e9fa6c
--- /dev/null
+++ b/ambari-common/src/main/python/ambari_jinja2/examples/rwbench/djangoext.py
@@ -0,0 +1,135 @@
+# -*- coding: utf-8 -*-
+from rwbench import ROOT
+from os.path import join
+from django.conf import settings
+settings.configure(
+    TEMPLATE_DIRS=(join(ROOT, 'django'),),
+    TEMPLATE_LOADERS=(
+        ('django.template.loaders.cached.Loader', (
+            'django.template.loaders.filesystem.Loader',
+        )),
+    )
+)
+from django.template import loader as django_loader, Context as DjangoContext, \
+     Node, NodeList, Variable, TokenParser
+from django import template as django_template_module
+from django.template import Library
+
+
+# for django extensions.  We monkey patch our extensions in so that
+# we don't have to initialize a more complex django setup.
+django_extensions = django_template_module.Library()
+django_template_module.builtins.append(django_extensions)
+
+
+from rwbench import dateformat
+django_extensions.filter(dateformat)
+
+
+def var_or_none(x):
+    if x is not None:
+        return Variable(x)
+
+
+# and more django extensions
+@django_extensions.tag
+def input_field(parser, token):
+    p = TokenParser(token.contents)
+    args = [p.value()]
+    while p.more():
+        args.append(p.value())
+    return InputFieldNode(*args)
+
+
+@django_extensions.tag
+def textarea(parser, token):
+    p = TokenParser(token.contents)
+    args = [p.value()]
+    while p.more():
+        args.append(p.value())
+    return TextareaNode(*args)
+
+
+@django_extensions.tag
+def form(parser, token):
+    p = TokenParser(token.contents)
+    args = []
+    while p.more():
+        args.append(p.value())
+    body = parser.parse(('endform',))
+    parser.delete_first_token()
+    return FormNode(body, *args)
+
+
+class InputFieldNode(Node):
+
+    def __init__(self, name, type=None, value=None):
+        self.name = var_or_none(name)
+        self.type = var_or_none(type)
+        self.value = var_or_none(value)
+
+    def render(self, context):
+        name = self.name.resolve(context)
+        type = 'text'
+        value = ''
+        if self.type is not None:
+            type = self.type.resolve(context)
+        if self.value is not None:
+            value = self.value.resolve(context)
+        tmpl = django_loader.get_template('_input_field.html')
+        return tmpl.render(DjangoContext({
+            'name':     name,
+            'type':     type,
+            'value':    value
+        }))
+
+
+class TextareaNode(Node):
+
+    def __init__(self, name, rows=None, cols=None, value=None):
+        self.name = var_or_none(name)
+        self.rows = var_or_none(rows)
+        self.cols = var_or_none(cols)
+        self.value = var_or_none(value)
+
+    def render(self, context):
+        name = self.name.resolve(context)
+        rows = 10
+        cols = 40
+        value = ''
+        if self.rows is not None:
+            rows = int(self.rows.resolve(context))
+        if self.cols is not None:
+            cols = int(self.cols.resolve(context))
+        if self.value is not None:
+            value = self.value.resolve(context)
+        tmpl = django_loader.get_template('_textarea.html')
+        return tmpl.render(DjangoContext({
+            'name':     name,
+            'rows':     rows,
+            'cols':     cols,
+            'value':    value
+        }))
+
+
+class FormNode(Node):
+
+    def __init__(self, body, action=None, method=None):
+        self.body = body
+        self.action = action
+        self.method = method
+
+    def render(self, context):
+        body = self.body.render(context)
+        action = ''
+        method = 'post'
+        if self.action is not None:
+            action = self.action.resolve(context)
+        if self.method is not None:
+            method = self.method.resolve(context)
+        tmpl = django_loader.get_template('_form.html')
+        return tmpl.render(DjangoContext({
+            'body':     body,
+            'action':   action,
+            'method':   method
+        }))

http://git-wip-us.apache.org/repos/asf/ambari/blob/7c3ea59f/ambari-common/src/main/python/ambari_jinja2/examples/rwbench/genshi/helpers.html
----------------------------------------------------------------------
diff --git a/ambari-common/src/main/python/ambari_jinja2/examples/rwbench/genshi/helpers.html b/ambari-common/src/main/python/ambari_jinja2/examples/rwbench/genshi/helpers.html
new file mode 100644
index 0000000..ecc6dc4
--- /dev/null
+++ b/ambari-common/src/main/python/ambari_jinja2/examples/rwbench/genshi/helpers.html
@@ -0,0 +1,12 @@
+<div xmlns="http://www.w3.org/1999/xhtml" xmlns:py="http://genshi.edgewall.org/"
+     py:strip="">
+
+  <py:def function="input_field(name='', value='', type='text')">
+    <input type="$type" value="$value" name="$name" />
+  </py:def>
+
+  <py:def function="textarea(name, value='', rows=10, cols=40)">
+    <textarea name="$name" rows="$rows" cols="cols">$value</textarea>
+  </py:def>
+
+</div>

http://git-wip-us.apache.org/repos/asf/ambari/blob/7c3ea59f/ambari-common/src/main/python/ambari_jinja2/examples/rwbench/genshi/index.html
----------------------------------------------------------------------
diff --git a/ambari-common/src/main/python/ambari_jinja2/examples/rwbench/genshi/index.html b/ambari-common/src/main/python/ambari_jinja2/examples/rwbench/genshi/index.html
new file mode 100644
index 0000000..70f697d
--- /dev/null
+++ b/ambari-common/src/main/python/ambari_jinja2/examples/rwbench/genshi/index.html
@@ -0,0 +1,41 @@
+<?python
+  from rwbench import dateformat
+?>
+<html xmlns="http://www.w3.org/1999/xhtml" xmlns:xi="http://www.w3.org/2001/XInclude"
+      xmlns:py="http://genshi.edgewall.org/">
+  <xi:include href="layout.html" />
+  <xi:include href="helpers.html" />
+  <head><title>Index Page</title></head>
+  <body>
+    <div class="article" py:for="article in articles">
+      <py:if test="article.published">
+        <h2><a href="${article.href}">${article.title}</a></h2>
+        <p class="meta">written by <a href="${article.user.href}"
+          >${article.user.username}</a> on ${dateformat(article.pub_date)}</p>
+        <div class="text">${Markup(article.body)}</div>
+      </py:if>
+    </div>
+    <!--
+      For a fair and balanced comparison we would have to use a def here
+      that wraps the form data but I don't know what would be the best
+      Genshi equivalent for that.  Quite frankly I doubt that this makes
+      sense in Genshi anyways.
+    -->
+    <form action="" method="post">
+      <dl>
+        <dt>Name</dt>
+        <dd>${input_field('name')}</dd>
+        <dt>E-Mail</dt>
+        <dd>${input_field('email')}</dd>
+        <dt>URL</dt>
+        <dd>${input_field('url')}</dd>
+        <dt>Comment</dt>
+        <dd>${textarea('comment')}</dd>
+        <dt>Captcha</dt>
+        <dd>${input_field('captcha')}</dd>
+      </dl>
+      ${input_field(type='submit', value='Submit')}
+      ${input_field(name='cancel', type='submit', value='Cancel')}
+    </form>
+  </body>
+</html>

http://git-wip-us.apache.org/repos/asf/ambari/blob/7c3ea59f/ambari-common/src/main/python/ambari_jinja2/examples/rwbench/genshi/layout.html
----------------------------------------------------------------------
diff --git a/ambari-common/src/main/python/ambari_jinja2/examples/rwbench/genshi/layout.html b/ambari-common/src/main/python/ambari_jinja2/examples/rwbench/genshi/layout.html
new file mode 100644
index 0000000..b12aec4
--- /dev/null
+++ b/ambari-common/src/main/python/ambari_jinja2/examples/rwbench/genshi/layout.html
@@ -0,0 +1,30 @@
+<html xmlns="http://www.w3.org/1999/xhtml" xmlns:py="http://genshi.edgewall.org/" >
+  <py:match path="head" once="true">
+    <head>
+      <title>${select('title/text()')} | RealWorld Benchmark</title>
+      <meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
+    </head>
+  </py:match>
+  <py:match path="body" once="true">
+    <body>
+      <div class="contents">
+        <div class="header">
+          <h1>RealWorld Benchmark</h1>
+          <blockquote><p>
+            A less stupid benchmark for Mako and Jinja2 to get an impression how
+            code changes affect runtime performance.
+          </p></blockquote>
+        </div>
+        <ul class="navigation">
+          <li py:for="href, caption in page_navigation"><a href="$href">$caption</a></li>
+        </ul>
+        <div class="body">
+          ${select('*|text()')}
+        </div>
+        <div class="footer">
+          &copy; Copyright 2008 by I don't know who.
+        </div>
+      </div>
+    </body>
+  </py:match>
+</html>

http://git-wip-us.apache.org/repos/asf/ambari/blob/7c3ea59f/ambari-common/src/main/python/ambari_jinja2/examples/rwbench/jinja/helpers.html
----------------------------------------------------------------------
diff --git a/ambari-common/src/main/python/ambari_jinja2/examples/rwbench/jinja/helpers.html b/ambari-common/src/main/python/ambari_jinja2/examples/rwbench/jinja/helpers.html
new file mode 100644
index 0000000..89976aa
--- /dev/null
+++ b/ambari-common/src/main/python/ambari_jinja2/examples/rwbench/jinja/helpers.html
@@ -0,0 +1,12 @@
+{% macro input_field(name, value='', type='text') -%}
+  <input type="{{ type }}" value="{{ value|e }}" name="{{ name }}">
+{%- endmacro %}
+
+{% macro textarea(name, value='', rows=10, cols=40) -%}
+  <textarea name="{{ name }}" rows="{{ rows }}" cols="{{ cols }}">{{
+    value|e }}</textarea>
+{%- endmacro %}
+
+{% macro form(action='', method='post') -%}
+  <form action="{{ action|e }}" method="{{ method }}">{{ caller() }}</form>
+{%- endmacro %}

http://git-wip-us.apache.org/repos/asf/ambari/blob/7c3ea59f/ambari-common/src/main/python/ambari_jinja2/examples/rwbench/jinja/index.html
----------------------------------------------------------------------
diff --git a/ambari-common/src/main/python/ambari_jinja2/examples/rwbench/jinja/index.html b/ambari-common/src/main/python/ambari_jinja2/examples/rwbench/jinja/index.html
new file mode 100644
index 0000000..b006d05
--- /dev/null
+++ b/ambari-common/src/main/python/ambari_jinja2/examples/rwbench/jinja/index.html
@@ -0,0 +1,29 @@
+{% extends "layout.html" %}
+{% from "helpers.html" import input_field, textarea, form %}
+{% block page_title %}Index Page{% endblock %}
+{% block body %}
+  {%- for article in articles if article.published %}
+  <div class="article">
+    <h2><a href="{{ article.href|e }}">{{ article.title|e }}</a></h2>
+    <p class="meta">written by <a href="{{ article.user.href|e
+      }}">{{ article.user.username|e }}</a> on {{ article.pub_date|dateformat }}</p>
+    <div class="text">{{ article.body }}</div>
+  </div>
+  {%- endfor %}
+  {%- call form() %}
+    <dl>
+      <dt>Name</dt>
+      <dd>{{ input_field('name') }}</dd>
+      <dt>E-Mail</dt>
+      <dd>{{ input_field('email') }}</dd>
+      <dt>URL</dt>
+      <dd>{{ input_field('url') }}</dd>
+      <dt>Comment</dt>
+      <dd>{{ textarea('comment') }}</dd>
+      <dt>Captcha</dt>
+      <dd>{{ input_field('captcha') }}</dd>
+    </dl>
+    {{ input_field(type='submit', value='Submit') }}
+    {{ input_field('cancel', type='submit', value='Cancel') }}
+  {%- endcall %}
+{% endblock %}

http://git-wip-us.apache.org/repos/asf/ambari/blob/7c3ea59f/ambari-common/src/main/python/ambari_jinja2/examples/rwbench/jinja/layout.html
----------------------------------------------------------------------
diff --git a/ambari-common/src/main/python/ambari_jinja2/examples/rwbench/jinja/layout.html b/ambari-common/src/main/python/ambari_jinja2/examples/rwbench/jinja/layout.html
new file mode 100644
index 0000000..755789e
--- /dev/null
+++ b/ambari-common/src/main/python/ambari_jinja2/examples/rwbench/jinja/layout.html
@@ -0,0 +1,29 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN" "http://www.w3.org/TR/html4/strict.dtd">
+<html>
+<head>
+  <title>{% block page_title %}{% endblock %} | RealWorld Benchmark</title>
+  <meta http-equiv="Content-Type" content="text/html; charset=utf-8">
+</head>
+<body>
+  <div class="contents">
+    <div class="header">
+      <h1>RealWorld Benchmark</h1>
+      <blockquote><p>
+        A less stupid benchmark for Mako and Jinja2 to get an impression how
+        code changes affect runtime performance.
+      </p></blockquote>
+    </div>
+    <ul class="navigation">
+    {%- for href, caption in page_navigation %}
+      <li><a href="{{ href|e }}">{{ caption }}</a></li>
+    {%- endfor %}
+    </ul>
+    <div class="body">
+      {% block body %}{% endblock %}
+    </div>
+    <div class="footer">
+      &copy; Copyright 2008 by I don't know who.
+    </div>
+  </div>
+</body>
+</html>

http://git-wip-us.apache.org/repos/asf/ambari/blob/7c3ea59f/ambari-common/src/main/python/ambari_jinja2/examples/rwbench/mako/helpers.html
----------------------------------------------------------------------
diff --git a/ambari-common/src/main/python/ambari_jinja2/examples/rwbench/mako/helpers.html b/ambari-common/src/main/python/ambari_jinja2/examples/rwbench/mako/helpers.html
new file mode 100644
index 0000000..a0290eb
--- /dev/null
+++ b/ambari-common/src/main/python/ambari_jinja2/examples/rwbench/mako/helpers.html
@@ -0,0 +1,11 @@
+<%def name="input_field(name='', value='', type='text')">
+  <input type="${type}" value="${value|h}" name="${name}">
+</%def>
+
+<%def name="textarea(name, value='', rows=10, cols=40)">
+  <textarea name="${name}" rows="${rows}" cols="${cols}">${value|h}</textarea>
+</%def>
+
+<%def name="form(action='', method='post')">
+  <form action="${action|h}" method="${method}">${caller.body()}</form>
+</%def>

http://git-wip-us.apache.org/repos/asf/ambari/blob/7c3ea59f/ambari-common/src/main/python/ambari_jinja2/examples/rwbench/mako/index.html
----------------------------------------------------------------------
diff --git a/ambari-common/src/main/python/ambari_jinja2/examples/rwbench/mako/index.html b/ambari-common/src/main/python/ambari_jinja2/examples/rwbench/mako/index.html
new file mode 100644
index 0000000..c4c6303
--- /dev/null
+++ b/ambari-common/src/main/python/ambari_jinja2/examples/rwbench/mako/index.html
@@ -0,0 +1,31 @@
+<%!
+  from rwbench import dateformat
+%>
+<%inherit file="layout.html" />
+<%namespace file="helpers.html" import="input_field, textarea, form" />
+<%def name="page_title()">Index Page</%def>
+% for article in articles:
+  <% if not article.published: continue %>
+<div class="article">
+  <h2><a href="${article.href|h}">${article.title|h}</a></h2>
+  <p class="meta">written by <a href="${article.user.href|h
+    }">${article.user.username|h}</a> on ${dateformat(article.pub_date)}</p>
+  <div class="text">${article.body}</div>
+</div>
+% endfor
+<%call expr="form()">
+  <dl>
+    <dt>Name</dt>
+    <dd>${input_field('name')}</dd>
+    <dt>E-Mail</dt>
+    <dd>${input_field('email')}</dd>
+    <dt>URL</dt>
+    <dd>${input_field('url')}</dd>
+    <dt>Comment</dt>
+    <dd>${textarea('comment')}</dd>
+    <dt>Captcha</dt>
+    <dd>${input_field('captcha')}</dd>
+  </dl>
+  ${input_field(type='submit', value='Submit')}
+  ${input_field(name='cancel', type='submit', value='Cancel')}
+</%call>

http://git-wip-us.apache.org/repos/asf/ambari/blob/7c3ea59f/ambari-common/src/main/python/ambari_jinja2/examples/rwbench/mako/layout.html
----------------------------------------------------------------------
diff --git a/ambari-common/src/main/python/ambari_jinja2/examples/rwbench/mako/layout.html b/ambari-common/src/main/python/ambari_jinja2/examples/rwbench/mako/layout.html
new file mode 100644
index 0000000..a9c353e
--- /dev/null
+++ b/ambari-common/src/main/python/ambari_jinja2/examples/rwbench/mako/layout.html
@@ -0,0 +1,30 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN" "http://www.w3.org/TR/html4/strict.dtd">
+<html>
+<head>
+  <title>${self.page_title()} | RealWorld Benchmark</title>
+  <meta http-equiv="Content-Type" content="text/html; charset=utf-8">
+</head>
+<body>
+  <div class="contents">
+    <div class="header">
+      <h1>RealWorld Benchmark</h1>
+      <blockquote><p>
+        A less stupid benchmark for Mako and Jinja2 to get an impression how
+        code changes affect runtime performance.
+      </p></blockquote>
+    </div>
+    <ul class="navigation">
+    % for href, caption in page_navigation:
+      <li><a href="${href|h}">${caption}</a></li>
+    % endfor
+    </ul>
+    <div class="body">
+      ${self.body()}
+    </div>
+    <div class="footer">
+      &copy; Copyright 2008 by I don't know who.
+    </div>
+  </div>
+</body>
+</html>
+<%def name="page_title()"></%def>

http://git-wip-us.apache.org/repos/asf/ambari/blob/7c3ea59f/ambari-common/src/main/python/ambari_jinja2/examples/rwbench/rwbench.py
----------------------------------------------------------------------
diff --git a/ambari-common/src/main/python/ambari_jinja2/examples/rwbench/rwbench.py b/ambari-common/src/main/python/ambari_jinja2/examples/rwbench/rwbench.py
new file mode 100644
index 0000000..35c7a1d
--- /dev/null
+++ b/ambari-common/src/main/python/ambari_jinja2/examples/rwbench/rwbench.py
@@ -0,0 +1,112 @@
+# -*- coding: utf-8 -*-
+"""
+    RealWorldish Benchmark
+    ~~~~~~~~~~~~~~~~~~~~~~
+
+    A more real-world benchmark of Jinja2.  Like the other benchmark in the
+    Jinja2 repository this has no real-world usefulnes (despite the name).
+    Just go away and ignore it.  NOW!
+
+    :copyright: (c) 2009 by the Jinja Team.
+    :license: BSD.
+"""
+import sys
+from os.path import join, dirname, abspath
+try:
+    from cProfile import Profile
+except ImportError:
+    from profile import Profile
+from pstats import Stats
+ROOT = abspath(dirname(__file__))
+
+from random import choice, randrange
+from datetime import datetime
+from timeit import Timer
+from ambari_jinja2 import Environment, FileSystemLoader
+from ambari_jinja2.utils import generate_lorem_ipsum
+from mako.lookup import TemplateLookup
+from genshi.template import TemplateLoader as GenshiTemplateLoader
+
+
+def dateformat(x):
+    return x.strftime('%Y-%m-%d')
+
+
+jinja_env = Environment(loader=FileSystemLoader(join(ROOT, 'jinja')))
+jinja_env.filters['dateformat'] = dateformat
+mako_lookup = TemplateLookup(directories=[join(ROOT, 'mako')])
+genshi_loader = GenshiTemplateLoader([join(ROOT, 'genshi')])
+
+class Article(object):
+
+    def __init__(self, id):
+        self.id = id
+        self.href = '/article/%d' % self.id
+        self.title = generate_lorem_ipsum(1, False, 5, 10)
+        self.user = choice(users)
+        self.body = generate_lorem_ipsum()
+        self.pub_date = datetime.utcfromtimestamp(randrange(10 ** 9, 2 * 10 ** 9))
+        self.published = True
+
+
+class User(object):
+
+    def __init__(self, username):
+        self.href = '/user/%s' % username
+        self.username = username
+
+
+users = map(User, [u'John Doe', u'Jane Doe', u'Peter Somewhat'])
+articles = map(Article, range(20))
+navigation = [
+    ('index',           'Index'),
+    ('about',           'About'),
+    ('foo?bar=1',       'Foo with Bar'),
+    ('foo?bar=2&s=x',   'Foo with X'),
+    ('blah',            'Blub Blah'),
+    ('hehe',            'Haha'),
+] * 5
+
+context = dict(users=users, articles=articles, page_navigation=navigation)
+
+
+jinja_template = jinja_env.get_template('index.html')
+mako_template = mako_lookup.get_template('index.html')
+genshi_template = genshi_loader.load('index.html')
+
+
+def test_jinja():
+    jinja_template.render(context)
+
+def test_mako():
+    mako_template.render_unicode(**context)
+
+
+from djangoext import django_loader, DjangoContext
+def test_django():
+    # not cached because django is not thread safe and does
+    # not cache by itself so it would be unfair to cache it here.
+    django_template = django_loader.get_template('index.html')
+    django_template.render(DjangoContext(context))
+
+
+def test_genshi():
+    genshi_template.generate(**context).render('html', doctype='html')
+
+
+if __name__ == '__main__':
+    sys.stdout.write('Realworldish Benchmark:\n')
+    for test in 'jinja', 'mako', 'django', 'genshi':
+        t = Timer(setup='from __main__ import test_%s as bench' % test,
+                  stmt='bench()')
+        sys.stdout.write(' >> %-20s<running>' % test)
+        sys.stdout.flush()
+        sys.stdout.write('\r    %-20s%.4f seconds\n' % (test, t.timeit(number=200) / 200))
+
+    if '-p' in sys.argv:
+        print 'Jinja profile'
+        p = Profile()
+        p.runcall(test_jinja)
+        stats = Stats(p)
+        stats.sort_stats('time', 'calls')
+        stats.print_stats()

http://git-wip-us.apache.org/repos/asf/ambari/blob/7c3ea59f/ambari-common/src/main/python/ambari_jinja2/ext/Vim/htmljinja.vim
----------------------------------------------------------------------
diff --git a/ambari-common/src/main/python/ambari_jinja2/ext/Vim/htmljinja.vim b/ambari-common/src/main/python/ambari_jinja2/ext/Vim/htmljinja.vim
new file mode 100644
index 0000000..3f9cba4
--- /dev/null
+++ b/ambari-common/src/main/python/ambari_jinja2/ext/Vim/htmljinja.vim
@@ -0,0 +1,27 @@
+" Vim syntax file
+" Language:	Jinja HTML template
+" Maintainer:	Armin Ronacher <ar...@active-4.com>
+" Last Change:	2007 Apr 8
+
+" For version 5.x: Clear all syntax items
+" For version 6.x: Quit when a syntax file was already loaded
+if version < 600
+  syntax clear
+elseif exists("b:current_syntax")
+  finish
+endif
+
+if !exists("main_syntax")
+  let main_syntax = 'html'
+endif
+
+if version < 600
+  so <sfile>:p:h/jinja.vim
+  so <sfile>:p:h/html.vim
+else
+  runtime! syntax/jinja.vim
+  runtime! syntax/html.vim
+  unlet b:current_syntax
+endif
+
+let b:current_syntax = "htmljinja"

http://git-wip-us.apache.org/repos/asf/ambari/blob/7c3ea59f/ambari-common/src/main/python/ambari_jinja2/ext/Vim/jinja.vim
----------------------------------------------------------------------
diff --git a/ambari-common/src/main/python/ambari_jinja2/ext/Vim/jinja.vim b/ambari-common/src/main/python/ambari_jinja2/ext/Vim/jinja.vim
new file mode 100644
index 0000000..919954b
--- /dev/null
+++ b/ambari-common/src/main/python/ambari_jinja2/ext/Vim/jinja.vim
@@ -0,0 +1,113 @@
+" Vim syntax file
+" Language:	Jinja template
+" Maintainer:	Armin Ronacher <ar...@active-4.com>
+" Last Change:	2008 May 9
+" Version:      1.1
+"
+" Known Bugs:
+"   because of odd limitations dicts and the modulo operator
+"   appear wrong in the template.
+"
+" Changes:
+"
+"     2008 May 9:     Added support for Jinja2 changes (new keyword rules)
+
+" For version 5.x: Clear all syntax items
+" For version 6.x: Quit when a syntax file was already loaded
+if version < 600
+  syntax clear
+elseif exists("b:current_syntax")
+  finish
+endif
+
+syntax case match
+
+" Jinja template built-in tags and parameters (without filter, macro, is and raw, they
+" have special threatment)
+syn keyword jinjaStatement containedin=jinjaVarBlock,jinjaTagBlock,jinjaNested contained and if else in not or recursive as import
+
+syn keyword jinjaStatement containedin=jinjaVarBlock,jinjaTagBlock,jinjaNested contained is filter skipwhite nextgroup=jinjaFilter
+syn keyword jinjaStatement containedin=jinjaTagBlock contained macro skipwhite nextgroup=jinjaFunction
+syn keyword jinjaStatement containedin=jinjaTagBlock contained block skipwhite nextgroup=jinjaBlockName
+
+" Variable Names
+syn match jinjaVariable containedin=jinjaVarBlock,jinjaTagBlock,jinjaNested contained skipwhite /[a-zA-Z_][a-zA-Z0-9_]*/
+syn keyword jinjaSpecial containedin=jinjaVarBlock,jinjaTagBlock,jinjaNested contained false true none False True None loop super caller varargs kwargs
+
+" Filters
+syn match jinjaOperator "|" containedin=jinjaVarBlock,jinjaTagBlock,jinjaNested contained nextgroup=jinjaFilter
+syn match jinjaFilter contained skipwhite /[a-zA-Z_][a-zA-Z0-9_]*/
+syn match jinjaFunction contained skipwhite /[a-zA-Z_][a-zA-Z0-9_]*/
+syn match jinjaBlockName contained skipwhite /[a-zA-Z_][a-zA-Z0-9_]*/
+
+" Jinja template constants
+syn region jinjaString containedin=jinjaVarBlock,jinjaTagBlock,jinjaNested contained start=/"/ skip=/\\"/ end=/"/
+syn region jinjaString containedin=jinjaVarBlock,jinjaTagBlock,jinjaNested contained start=/'/ skip=/\\'/ end=/'/
+syn match jinjaNumber containedin=jinjaVarBlock,jinjaTagBlock,jinjaNested contained /[0-9]\+\(\.[0-9]\+\)\?/
+
+" Operators
+syn match jinjaOperator containedin=jinjaVarBlock,jinjaTagBlock,jinjaNested contained /[+\-*\/<>=!,:]/
+syn match jinjaPunctuation containedin=jinjaVarBlock,jinjaTagBlock,jinjaNested contained /[()\[\]]/
+syn match jinjaOperator containedin=jinjaVarBlock,jinjaTagBlock,jinjaNested contained /\./ nextgroup=jinjaAttribute
+syn match jinjaAttribute contained /[a-zA-Z_][a-zA-Z0-9_]*/
+
+" Jinja template tag and variable blocks
+syn region jinjaNested matchgroup=jinjaOperator start="(" end=")" transparent display containedin=jinjaVarBlock,jinjaTagBlock,jinjaNested contained
+syn region jinjaNested matchgroup=jinjaOperator start="\[" end="\]" transparent display containedin=jinjaVarBlock,jinjaTagBlock,jinjaNested contained
+syn region jinjaNested matchgroup=jinjaOperator start="{" end="}" transparent display containedin=jinjaVarBlock,jinjaTagBlock,jinjaNested contained
+syn region jinjaTagBlock matchgroup=jinjaTagDelim start=/{%-\?/ end=/-\?%}/ skipwhite containedin=ALLBUT,jinjaTagBlock,jinjaVarBlock,jinjaRaw,jinjaString,jinjaNested,jinjaComment
+
+syn region jinjaVarBlock matchgroup=jinjaVarDelim start=/{{-\?/ end=/-\?}}/ containedin=ALLBUT,jinjaTagBlock,jinjaVarBlock,jinjaRaw,jinjaString,jinjaNested,jinjaComment
+
+" Jinja template 'raw' tag
+syn region jinjaRaw matchgroup=jinjaRawDelim start="{%\s*raw\s*%}" end="{%\s*endraw\s*%}" containedin=ALLBUT,jinjaTagBlock,jinjaVarBlock,jinjaString,jinjaComment
+
+" Jinja comments
+syn region jinjaComment matchgroup=jinjaCommentDelim start="{#" end="#}" containedin=ALLBUT,jinjaTagBlock,jinjaVarBlock,jinjaString
+
+" Block start keywords.  A bit tricker.  We only highlight at the start of a
+" tag block and only if the name is not followed by a comma or equals sign
+" which usually means that we have to deal with an assignment.
+syn match jinjaStatement containedin=jinjaTagBlock contained skipwhite /\({%-\?\s*\)\@<=\<[a-zA-Z_][a-zA-Z0-9_]*\>\(\s*[,=]\)\@!/
+
+" and context modifiers
+syn match jinjaStatement containedin=jinjaTagBlock contained /\<with\(out\)\?\s\+context\>/ skipwhite
+
+
+" Define the default highlighting.
+" For version 5.7 and earlier: only when not done already
+" For version 5.8 and later: only when an item doesn't have highlighting yet
+if version >= 508 || !exists("did_jinja_syn_inits")
+  if version < 508
+    let did_jinja_syn_inits = 1
+    command -nargs=+ HiLink hi link <args>
+  else
+    command -nargs=+ HiLink hi def link <args>
+  endif
+
+  HiLink jinjaPunctuation jinjaOperator
+  HiLink jinjaAttribute jinjaVariable
+  HiLink jinjaFunction jinjaFilter
+
+  HiLink jinjaTagDelim jinjaTagBlock
+  HiLink jinjaVarDelim jinjaVarBlock
+  HiLink jinjaCommentDelim jinjaComment
+  HiLink jinjaRawDelim jinja
+
+  HiLink jinjaSpecial Special
+  HiLink jinjaOperator Normal
+  HiLink jinjaRaw Normal
+  HiLink jinjaTagBlock PreProc
+  HiLink jinjaVarBlock PreProc
+  HiLink jinjaStatement Statement
+  HiLink jinjaFilter Function
+  HiLink jinjaBlockName Function
+  HiLink jinjaVariable Identifier
+  HiLink jinjaString Constant
+  HiLink jinjaNumber Constant
+  HiLink jinjaComment Comment
+
+  delcommand HiLink
+endif
+
+let b:current_syntax = "jinja"

http://git-wip-us.apache.org/repos/asf/ambari/blob/7c3ea59f/ambari-common/src/main/python/ambari_jinja2/ext/django2jinja/django2jinja.py
----------------------------------------------------------------------
diff --git a/ambari-common/src/main/python/ambari_jinja2/ext/django2jinja/django2jinja.py b/ambari-common/src/main/python/ambari_jinja2/ext/django2jinja/django2jinja.py
new file mode 100644
index 0000000..d2f3b0d
--- /dev/null
+++ b/ambari-common/src/main/python/ambari_jinja2/ext/django2jinja/django2jinja.py
@@ -0,0 +1,768 @@
+# -*- coding: utf-8 -*-
+"""
+    Django to Jinja
+    ~~~~~~~~~~~~~~~
+
+    Helper module that can convert django templates into Jinja2 templates.
+
+    This file is not intended to be used as stand alone application but to
+    be used as library.  To convert templates you basically create your own
+    writer, add extra conversion logic for your custom template tags,
+    configure your django environment and run the `convert_templates`
+    function.
+
+    Here a simple example::
+
+        # configure django (or use settings.configure)
+        import os
+        os.environ['DJANGO_SETTINGS_MODULE'] = 'yourapplication.settings'
+        from yourapplication.foo.templatetags.bar import MyNode
+
+        from django2jinja import Writer, convert_templates
+
+        def write_my_node(writer, node):
+            writer.start_variable()
+            writer.write('myfunc(')
+            for idx, arg in enumerate(node.args):
+                if idx:
+                    writer.write(', ')
+                writer.node(arg)
+            writer.write(')')
+            writer.end_variable()
+
+        writer = Writer()
+        writer.node_handlers[MyNode] = write_my_node
+        convert_templates('/path/to/output/folder', writer=writer)
+    
+    Here is an example hos to automatically translate your django
+    variables to ambari_jinja2::
+        
+        import re
+        # List of tuple (Match pattern, Replace pattern, Exclusion pattern)
+        
+        var_re  = ((re.compile(r"(u|user)\.is_authenticated"), r"\1.is_authenticated()", None),
+                  (re.compile(r"\.non_field_errors"), r".non_field_errors()", None),
+                  (re.compile(r"\.label_tag"), r".label_tag()", None),
+                  (re.compile(r"\.as_dl"), r".as_dl()", None),
+                  (re.compile(r"\.as_table"), r".as_table()", None),
+                  (re.compile(r"\.as_widget"), r".as_widget()", None),
+                  (re.compile(r"\.as_hidden"), r".as_hidden()", None),
+                  
+                  (re.compile(r"\.get_([0-9_\w]+)_url"), r".get_\1_url()", None),
+                  (re.compile(r"\.url"), r".url()", re.compile(r"(form|calendar).url")),
+                  (re.compile(r"\.get_([0-9_\w]+)_display"), r".get_\1_display()", None),
+                  (re.compile(r"loop\.counter"), r"loop.index", None),
+                  (re.compile(r"loop\.revcounter"), r"loop.revindex", None),
+                  (re.compile(r"request\.GET\.([0-9_\w]+)"), r"request.GET.get('\1', '')", None),
+                  (re.compile(r"request\.get_host"), r"request.get_host()", None),
+                  
+                  (re.compile(r"\.all(?!_)"), r".all()", None),
+                  (re.compile(r"\.all\.0"), r".all()[0]", None),
+                  (re.compile(r"\.([0-9])($|\s+)"), r"[\1]\2", None),
+                  (re.compile(r"\.items"), r".items()", None),
+        )
+        writer = Writer(var_re=var_re)
+        
+    For details about the writing process have a look at the module code.
+
+    :copyright: (c) 2009 by the Jinja Team.
+    :license: BSD.
+"""
+import re
+import os
+import sys
+from ambari_jinja2.defaults import *
+from django.conf import settings
+from django.template import defaulttags as core_tags, loader, TextNode, \
+     FilterExpression, libraries, Variable, loader_tags, TOKEN_TEXT, \
+     TOKEN_VAR
+from django.template.debug import DebugVariableNode as VariableNode
+from django.templatetags import i18n as i18n_tags
+from StringIO import StringIO
+
+
+_node_handlers = {}
+_resolved_filters = {}
+_newline_re = re.compile(r'(?:\r\n|\r|\n)')
+
+
+# Django stores an itertools object on the cycle node.  Not only is this
+# thread unsafe but also a problem for the converter which needs the raw
+# string values passed to the constructor to create a jinja loop.cycle()
+# call from it.
+_old_cycle_init = core_tags.CycleNode.__init__
+def _fixed_cycle_init(self, cyclevars, variable_name=None):
+    self.raw_cycle_vars = map(Variable, cyclevars)
+    _old_cycle_init(self, cyclevars, variable_name)
+core_tags.CycleNode.__init__ = _fixed_cycle_init
+
+
+def node(cls):
+    def proxy(f):
+        _node_handlers[cls] = f
+        return f
+    return proxy
+
+
+def convert_templates(output_dir, extensions=('.html', '.txt'), writer=None,
+                      callback=None):
+    """Iterates over all templates in the template dirs configured and
+    translates them and writes the new templates into the output directory.
+    """
+    if writer is None:
+        writer = Writer()
+
+    def filter_templates(files):
+        for filename in files:
+            ifilename = filename.lower()
+            for extension in extensions:
+                if ifilename.endswith(extension):
+                    yield filename
+
+    def translate(f, loadname):
+        template = loader.get_template(loadname)
+        original = writer.stream
+        writer.stream = f
+        writer.body(template.nodelist)
+        writer.stream = original
+
+    if callback is None:
+        def callback(template):
+            print template
+
+    for directory in settings.TEMPLATE_DIRS:
+        for dirname, _, files in os.walk(directory):
+            dirname = dirname[len(directory) + 1:]
+            for filename in filter_templates(files):
+                source = os.path.normpath(os.path.join(dirname, filename))
+                target = os.path.join(output_dir, dirname, filename)
+                basetarget = os.path.dirname(target)
+                if not os.path.exists(basetarget):
+                    os.makedirs(basetarget)
+                callback(source)
+                f = file(target, 'w')
+                try:
+                    translate(f, source)
+                finally:
+                    f.close()
+
+
+class Writer(object):
+    """The core writer class."""
+
+    def __init__(self, stream=None, error_stream=None,
+                 block_start_string=BLOCK_START_STRING,
+                 block_end_string=BLOCK_END_STRING,
+                 variable_start_string=VARIABLE_START_STRING,
+                 variable_end_string=VARIABLE_END_STRING,
+                 comment_start_string=COMMENT_START_STRING,
+                 comment_end_string=COMMENT_END_STRING,
+                 initial_autoescape=True,
+                 use_jinja_autoescape=False,
+                 custom_node_handlers=None,
+                 var_re=[],
+                 env=None):
+        if stream is None:
+            stream = sys.stdout
+        if error_stream is None:
+            error_stream = sys.stderr
+        self.stream = stream
+        self.error_stream = error_stream
+        self.block_start_string = block_start_string
+        self.block_end_string = block_end_string
+        self.variable_start_string = variable_start_string
+        self.variable_end_string = variable_end_string
+        self.comment_start_string = comment_start_string
+        self.comment_end_string = comment_end_string
+        self.autoescape = initial_autoescape
+        self.spaceless = False
+        self.use_jinja_autoescape = use_jinja_autoescape
+        self.node_handlers = dict(_node_handlers,
+                                  **(custom_node_handlers or {}))
+        self._loop_depth = 0
+        self._filters_warned = set()
+        self.var_re = var_re
+        self.env = env
+
+    def enter_loop(self):
+        """Increments the loop depth so that write functions know if they
+        are in a loop.
+        """
+        self._loop_depth += 1
+
+    def leave_loop(self):
+        """Reverse of enter_loop."""
+        self._loop_depth -= 1
+
+    @property
+    def in_loop(self):
+        """True if we are in a loop."""
+        return self._loop_depth > 0
+
+    def write(self, s):
+        """Writes stuff to the stream."""
+        self.stream.write(s.encode(settings.FILE_CHARSET))
+
+    def print_expr(self, expr):
+        """Open a variable tag, write to the string to the stream and close."""
+        self.start_variable()
+        self.write(expr)
+        self.end_variable()
+
+    def _post_open(self):
+        if self.spaceless:
+            self.write('- ')
+        else:
+            self.write(' ')
+
+    def _pre_close(self):
+        if self.spaceless:
+            self.write(' -')
+        else:
+            self.write(' ')
+
+    def start_variable(self):
+        """Start a variable."""
+        self.write(self.variable_start_string)
+        self._post_open()
+
+    def end_variable(self, always_safe=False):
+        """End a variable."""
+        if not always_safe and self.autoescape and \
+           not self.use_jinja_autoescape:
+            self.write('|e')
+        self._pre_close()
+        self.write(self.variable_end_string)
+
+    def start_block(self):
+        """Starts a block."""
+        self.write(self.block_start_string)
+        self._post_open()
+
+    def end_block(self):
+        """Ends a block."""
+        self._pre_close()
+        self.write(self.block_end_string)
+
+    def tag(self, name):
+        """Like `print_expr` just for blocks."""
+        self.start_block()
+        self.write(name)
+        self.end_block()
+
+    def variable(self, name):
+        """Prints a variable.  This performs variable name transformation."""
+        self.write(self.translate_variable_name(name))
+
+    def literal(self, value):
+        """Writes a value as literal."""
+        value = repr(value)
+        if value[:2] in ('u"', "u'"):
+            value = value[1:]
+        self.write(value)
+
+    def filters(self, filters, is_block=False):
+        """Dumps a list of filters."""
+        want_pipe = not is_block
+        for filter, args in filters:
+            name = self.get_filter_name(filter)
+            if name is None:
+                self.warn('Could not find filter %s' % name)
+                continue
+            if name not in DEFAULT_FILTERS and \
+               name not in self._filters_warned:
+                self._filters_warned.add(name)
+                self.warn('Filter %s probably doesn\'t exist in Jinja' %
+                            name)
+            if not want_pipe:
+                want_pipe = True
+            else:
+                self.write('|')
+            self.write(name)
+            if args:
+                self.write('(')
+                for idx, (is_var, value) in enumerate(args):
+                    if idx:
+                        self.write(', ')
+                    if is_var:
+                        self.node(value)
+                    else:
+                        self.literal(value)
+                self.write(')')
+
+    def get_location(self, origin, position):
+        """Returns the location for an origin and position tuple as name
+        and lineno.
+        """
+        if hasattr(origin, 'source'):
+            source = origin.source
+            name = '<unknown source>'
+        else:
+            source = origin.loader(origin.loadname, origin.dirs)[0]
+            name = origin.loadname
+        lineno = len(_newline_re.findall(source[:position[0]])) + 1
+        return name, lineno
+
+    def warn(self, message, node=None):
+        """Prints a warning to the error stream."""
+        if node is not None and hasattr(node, 'source'):
+            filename, lineno = self.get_location(*node.source)
+            message = '[%s:%d] %s' % (filename, lineno, message)
+        print >> self.error_stream, message
+
+    def translate_variable_name(self, var):
+        """Performs variable name translation."""
+        if self.in_loop and var == 'forloop' or var.startswith('forloop.'):
+            var = var[3:]
+        
+        for reg, rep, unless in self.var_re:
+            no_unless = unless and unless.search(var) or True
+            if reg.search(var) and no_unless:
+                var = reg.sub(rep, var)
+                break
+        return var
+
+    def get_filter_name(self, filter):
+        """Returns the filter name for a filter function or `None` if there
+        is no such filter.
+        """
+        if filter not in _resolved_filters:
+            for library in libraries.values():
+                for key, value in library.filters.iteritems():
+                    _resolved_filters[value] = key
+        return _resolved_filters.get(filter, None)
+
+    def node(self, node):
+        """Invokes the node handler for a node."""
+        for cls, handler in self.node_handlers.iteritems():
+            if type(node) is cls or type(node).__name__ == cls:
+                handler(self, node)
+                break
+        else:
+            self.warn('Untranslatable node %s.%s found' % (
+                node.__module__,
+                node.__class__.__name__
+            ), node)
+
+    def body(self, nodes):
+        """Calls node() for every node in the iterable passed."""
+        for node in nodes:
+            self.node(node)
+
+
+@node(TextNode)
+def text_node(writer, node):
+    writer.write(node.s)
+
+
+@node(Variable)
+def variable(writer, node):
+    if node.translate:
+        writer.warn('i18n system used, make sure to install translations', node)
+        writer.write('_(')
+    if node.literal is not None:
+        writer.literal(node.literal)
+    else:
+        writer.variable(node.var)
+    if node.translate:
+        writer.write(')')
+
+
+@node(VariableNode)
+def variable_node(writer, node):
+    writer.start_variable()
+    if node.filter_expression.var.var == 'block.super' \
+       and not node.filter_expression.filters:
+        writer.write('super()')
+    else:
+        writer.node(node.filter_expression)
+    writer.end_variable()
+
+
+@node(FilterExpression)
+def filter_expression(writer, node):
+    writer.node(node.var)
+    writer.filters(node.filters)
+
+
+@node(core_tags.CommentNode)
+def comment_tag(writer, node):
+    pass
+
+
+@node(core_tags.DebugNode)
+def comment_tag(writer, node):
+    writer.warn('Debug tag detected.  Make sure to add a global function '
+                'called debug to the namespace.', node=node)
+    writer.print_expr('debug()')
+
+
+@node(core_tags.ForNode)
+def for_loop(writer, node):
+    writer.start_block()
+    writer.write('for ')
+    for idx, var in enumerate(node.loopvars):
+        if idx:
+            writer.write(', ')
+        writer.variable(var)
+    writer.write(' in ')
+    if node.is_reversed:
+        writer.write('(')
+    writer.node(node.sequence)
+    if node.is_reversed:
+        writer.write(')|reverse')
+    writer.end_block()
+    writer.enter_loop()
+    writer.body(node.nodelist_loop)
+    writer.leave_loop()
+    writer.tag('endfor')
+
+
+@node(core_tags.IfNode)
+def if_condition(writer, node):
+    writer.start_block()
+    writer.write('if ')
+    join_with = 'and'
+    if node.link_type == core_tags.IfNode.LinkTypes.or_:
+        join_with = 'or'
+    
+    for idx, (ifnot, expr) in enumerate(node.bool_exprs):
+        if idx:
+            writer.write(' %s ' % join_with)
+        if ifnot:
+            writer.write('not ')
+        writer.node(expr)
+    writer.end_block()
+    writer.body(node.nodelist_true)
+    if node.nodelist_false:
+        writer.tag('else')
+        writer.body(node.nodelist_false)
+    writer.tag('endif')
+
+
+@node(core_tags.IfEqualNode)
+def if_equal(writer, node):
+    writer.start_block()
+    writer.write('if ')
+    writer.node(node.var1)
+    if node.negate:
+        writer.write(' != ')
+    else:
+        writer.write(' == ')
+    writer.node(node.var2)
+    writer.end_block()
+    writer.body(node.nodelist_true)
+    if node.nodelist_false:
+        writer.tag('else')
+        writer.body(node.nodelist_false)
+    writer.tag('endif')
+
+
+@node(loader_tags.BlockNode)
+def block(writer, node):
+    writer.tag('block ' + node.name.replace('-', '_').rstrip('_'))
+    node = node
+    while node.parent is not None:
+        node = node.parent
+    writer.body(node.nodelist)
+    writer.tag('endblock')
+
+
+@node(loader_tags.ExtendsNode)
+def extends(writer, node):
+    writer.start_block()
+    writer.write('extends ')
+    if node.parent_name_expr:
+        writer.node(node.parent_name_expr)
+    else:
+        writer.literal(node.parent_name)
+    writer.end_block()
+    writer.body(node.nodelist)
+
+
+@node(loader_tags.ConstantIncludeNode)
+@node(loader_tags.IncludeNode)
+def include(writer, node):
+    writer.start_block()
+    writer.write('include ')
+    if hasattr(node, 'template'):
+        writer.literal(node.template.name)
+    else:
+        writer.node(node.template_name)
+    writer.end_block()
+
+
+@node(core_tags.CycleNode)
+def cycle(writer, node):
+    if not writer.in_loop:
+        writer.warn('Untranslatable free cycle (cycle outside loop)', node=node)
+        return
+    if node.variable_name is not None:
+        writer.start_block()
+        writer.write('set %s = ' % node.variable_name)
+    else:
+        writer.start_variable()
+    writer.write('loop.cycle(')
+    for idx, var in enumerate(node.raw_cycle_vars):
+        if idx:
+            writer.write(', ')
+        writer.node(var)
+    writer.write(')')
+    if node.variable_name is not None:
+        writer.end_block()
+    else:
+        writer.end_variable()
+
+
+@node(core_tags.FilterNode)
+def filter(writer, node):
+    writer.start_block()
+    writer.write('filter ')
+    writer.filters(node.filter_expr.filters, True)
+    writer.end_block()
+    writer.body(node.nodelist)
+    writer.tag('endfilter')
+
+
+@node(core_tags.AutoEscapeControlNode)
+def autoescape_control(writer, node):
+    original = writer.autoescape
+    writer.autoescape = node.setting
+    writer.body(node.nodelist)
+    writer.autoescape = original
+
+
+@node(core_tags.SpacelessNode)
+def spaceless(writer, node):
+    original = writer.spaceless
+    writer.spaceless = True
+    writer.warn('entering spaceless mode with different semantics', node)
+    # do the initial stripping
+    nodelist = list(node.nodelist)
+    if nodelist:
+        if isinstance(nodelist[0], TextNode):
+            nodelist[0] = TextNode(nodelist[0].s.lstrip())
+        if isinstance(nodelist[-1], TextNode):
+            nodelist[-1] = TextNode(nodelist[-1].s.rstrip())
+    writer.body(nodelist)
+    writer.spaceless = original
+
+
+@node(core_tags.TemplateTagNode)
+def template_tag(writer, node):
+    tag = {
+        'openblock':            writer.block_start_string,
+        'closeblock':           writer.block_end_string,
+        'openvariable':         writer.variable_start_string,
+        'closevariable':        writer.variable_end_string,
+        'opencomment':          writer.comment_start_string,
+        'closecomment':         writer.comment_end_string,
+        'openbrace':            '{',
+        'closebrace':           '}'
+    }.get(node.tagtype)
+    if tag:
+        writer.start_variable()
+        writer.literal(tag)
+        writer.end_variable()
+
+
+@node(core_tags.URLNode)
+def url_tag(writer, node):
+    writer.warn('url node used.  make sure to provide a proper url() '
+                'function', node)
+    if node.asvar:
+        writer.start_block()
+        writer.write('set %s = ' % node.asvar)
+    else:
+        writer.start_variable()
+    autoescape = writer.autoescape
+    writer.write('url(')
+    writer.literal(node.view_name)
+    for arg in node.args:
+        writer.write(', ')
+        writer.node(arg)
+    for key, arg in node.kwargs.items():
+        writer.write(', %s=' % key)
+        writer.node(arg)
+    writer.write(')')
+    if node.asvar:
+        writer.end_block()
+    else:
+        writer.end_variable()
+
+
+@node(core_tags.WidthRatioNode)
+def width_ratio(writer, node):
+    writer.warn('widthratio expanded into formula.  You may want to provide '
+                'a helper function for this calculation', node)
+    writer.start_variable()
+    writer.write('(')
+    writer.node(node.val_expr)
+    writer.write(' / ')
+    writer.node(node.max_expr)
+    writer.write(' * ')
+    writer.write(str(int(node.max_width)))
+    writer.write(')|round|int')
+    writer.end_variable(always_safe=True)
+
+
+@node(core_tags.WithNode)
+def with_block(writer, node):
+    writer.warn('with block expanded into set statement.  This could cause '
+                'variables following that block to be overriden.', node)
+    writer.start_block()
+    writer.write('set %s = ' % node.name)
+    writer.node(node.var)
+    writer.end_block()
+    writer.body(node.nodelist)
+
+
+@node(core_tags.RegroupNode)
+def regroup(writer, node):
+    if node.expression.var.literal:
+        writer.warn('literal in groupby filter used.   Behavior in that '
+                    'situation is undefined and translation is skipped.', node)
+        return
+    elif node.expression.filters:
+        writer.warn('filters in groupby filter used.   Behavior in that '
+                    'situation is undefined which is most likely a bug '
+                    'in your code.  Filters were ignored.', node)
+    writer.start_block()
+    writer.write('set %s = ' % node.var_name)
+    writer.node(node.target)
+    writer.write('|groupby(')
+    writer.literal(node.expression.var.var)
+    writer.write(')')
+    writer.end_block()
+
+
+@node(core_tags.LoadNode)
+def warn_load(writer, node):
+    writer.warn('load statement used which was ignored on conversion', node)
+
+
+@node(i18n_tags.GetAvailableLanguagesNode)
+def get_available_languages(writer, node):
+    writer.warn('make sure to provide a get_available_languages function', node)
+    writer.tag('set %s = get_available_languages()' %
+               writer.translate_variable_name(node.variable))
+
+
+@node(i18n_tags.GetCurrentLanguageNode)
+def get_current_language(writer, node):
+    writer.warn('make sure to provide a get_current_language function', node)
+    writer.tag('set %s = get_current_language()' %
+               writer.translate_variable_name(node.variable))
+
+
+@node(i18n_tags.GetCurrentLanguageBidiNode)
+def get_current_language_bidi(writer, node):
+    writer.warn('make sure to provide a get_current_language_bidi function', node)
+    writer.tag('set %s = get_current_language_bidi()' %
+               writer.translate_variable_name(node.variable))
+
+
+@node(i18n_tags.TranslateNode)
+def simple_gettext(writer, node):
+    writer.warn('i18n system used, make sure to install translations', node)
+    writer.start_variable()
+    writer.write('_(')
+    writer.node(node.value)
+    writer.write(')')
+    writer.end_variable()
+
+
+@node(i18n_tags.BlockTranslateNode)
+def translate_block(writer, node):
+    first_var = []
+    variables = set()
+
+    def touch_var(name):
+        variables.add(name)
+        if not first_var:
+            first_var.append(name)
+
+    def dump_token_list(tokens):
+        for token in tokens:
+            if token.token_type == TOKEN_TEXT:
+                writer.write(token.contents)
+            elif token.token_type == TOKEN_VAR:
+                writer.print_expr(token.contents)
+                touch_var(token.contents)
+
+    writer.warn('i18n system used, make sure to install translations', node)
+    writer.start_block()
+    writer.write('trans')
+    idx = -1
+    for idx, (key, var) in enumerate(node.extra_context.items()):
+        if idx:
+            writer.write(',')
+        writer.write(' %s=' % key)
+        touch_var(key)
+        writer.node(var.filter_expression)
+
+    have_plural = False
+    plural_var = None
+    if node.plural and node.countervar and node.counter:
+        have_plural = True
+        plural_var = node.countervar
+        if plural_var not in variables:
+            if idx > -1:
+                writer.write(',')
+            touch_var(plural_var)
+            writer.write(' %s=' % plural_var)
+            writer.node(node.counter)
+
+    writer.end_block()
+    dump_token_list(node.singular)
+    if node.plural and node.countervar and node.counter:
+        writer.start_block()
+        writer.write('pluralize')
+        if node.countervar != first_var[0]:
+            writer.write(' ' + node.countervar)
+        writer.end_block()
+        dump_token_list(node.plural)
+    writer.tag('endtrans')
+
+@node("SimpleNode")
+def simple_tag(writer, node):
+    """Check if the simple tag exist as a filter in """
+    name = node.tag_name
+    if writer.env and \
+       name not in writer.env.filters and \
+       name not in writer._filters_warned:
+        writer._filters_warned.add(name)
+        writer.warn('Filter %s probably doesn\'t exist in Jinja' %
+                    name)
+        
+    if not node.vars_to_resolve:
+        # No argument, pass the request
+        writer.start_variable()
+        writer.write('request|')
+        writer.write(name)
+        writer.end_variable()
+        return 
+    
+    first_var =  node.vars_to_resolve[0]
+    args = node.vars_to_resolve[1:]
+    writer.start_variable()
+    
+    # Copied from Writer.filters()
+    writer.node(first_var)
+    
+    writer.write('|')
+    writer.write(name)
+    if args:
+        writer.write('(')
+        for idx, var in enumerate(args):
+            if idx:
+                writer.write(', ')
+            if var.var:
+                writer.node(var)
+            else:
+                writer.literal(var.literal)
+        writer.write(')')
+    writer.end_variable()   
+
+# get rid of node now, it shouldn't be used normally
+del node

http://git-wip-us.apache.org/repos/asf/ambari/blob/7c3ea59f/ambari-common/src/main/python/ambari_jinja2/ext/django2jinja/example.py
----------------------------------------------------------------------
diff --git a/ambari-common/src/main/python/ambari_jinja2/ext/django2jinja/example.py b/ambari-common/src/main/python/ambari_jinja2/ext/django2jinja/example.py
new file mode 100644
index 0000000..2d4ab9a
--- /dev/null
+++ b/ambari-common/src/main/python/ambari_jinja2/ext/django2jinja/example.py
@@ -0,0 +1,7 @@
+from django.conf import settings
+settings.configure(TEMPLATE_DIRS=['templates'], TEMPLATE_DEBUG=True)
+
+from django2jinja import convert_templates, Writer
+
+writer = Writer(use_jinja_autoescape=True)
+convert_templates('converted', writer=writer)

http://git-wip-us.apache.org/repos/asf/ambari/blob/7c3ea59f/ambari-common/src/main/python/ambari_jinja2/ext/django2jinja/templates/index.html
----------------------------------------------------------------------
diff --git a/ambari-common/src/main/python/ambari_jinja2/ext/django2jinja/templates/index.html b/ambari-common/src/main/python/ambari_jinja2/ext/django2jinja/templates/index.html
new file mode 100644
index 0000000..d0fbe38
--- /dev/null
+++ b/ambari-common/src/main/python/ambari_jinja2/ext/django2jinja/templates/index.html
@@ -0,0 +1,58 @@
+{% extends "layout.html" %}
+{% load i18n %}
+{% block title %}Foo{% endblock %}
+{% block page-body %}
+  {{ block.super }}
+  Hello {{ name|cut:"d" }}!
+
+  {% for item in seq reversed %}
+    {% if forloop.index|divisibleby:2 %}
+      <li class="{% cycle 'a' 'b' %}">{{ item }}</li>
+    {% endif %}
+  {% endfor %}
+  {% ifequal foo bar %}
+    haha
+  {% else %}
+    hmm
+  {% endifequal %}
+  {% filter upper %}
+    {% include "subtemplate.html" %}
+    {% include foo %}
+  {% endfilter %}
+  {% spaceless %}
+    Hello World
+      {{ foo }}
+    Hmm
+  {% endspaceless %}
+  {% templatetag opencomment %}...{% templatetag closecomment %}
+  {% url foo a, b, c=d %}
+  {% url foo a, b, c=d as hmm %}
+
+  {% with object.value as value %}
+    <img src='bar.gif' height='10' width='{% widthratio value 200 100 %}'>
+  {% endwith %}
+
+  <pre>{% debug %}</pre>
+
+  {% blocktrans with book|title as book_t and author|title as author_t %}
+  This is {{ book_t }} by {{ author_t }}
+  {% endblocktrans %}
+
+  {% blocktrans count list|length as counter %}
+  There is only one {{ name }} object.
+  {% plural %}
+  There are {{ counter }} {{ name }} objects.
+  {% endblocktrans %}
+
+  {% blocktrans with name|escape as name count list|length as counter %}
+  There is only one {{ name }} object.
+  {% plural %}
+  There are {{ counter }} {{ name }} objects.
+  {% endblocktrans %}
+
+  {% blocktrans %}This string will have {{ value }} inside.{% endblocktrans %}
+
+  <p>{% trans "This is the title." %}</p>
+
+  {% regroup people by gender as grouped %}
+{% endblock %}

http://git-wip-us.apache.org/repos/asf/ambari/blob/7c3ea59f/ambari-common/src/main/python/ambari_jinja2/ext/django2jinja/templates/layout.html
----------------------------------------------------------------------
diff --git a/ambari-common/src/main/python/ambari_jinja2/ext/django2jinja/templates/layout.html b/ambari-common/src/main/python/ambari_jinja2/ext/django2jinja/templates/layout.html
new file mode 100644
index 0000000..3f21a12
--- /dev/null
+++ b/ambari-common/src/main/python/ambari_jinja2/ext/django2jinja/templates/layout.html
@@ -0,0 +1,4 @@
+<title>{% block title %}{% endblock %}</title>
+<div class="body">
+  {% block page-body %}{% endblock %}
+</div>

http://git-wip-us.apache.org/repos/asf/ambari/blob/7c3ea59f/ambari-common/src/main/python/ambari_jinja2/ext/django2jinja/templates/subtemplate.html
----------------------------------------------------------------------
diff --git a/ambari-common/src/main/python/ambari_jinja2/ext/django2jinja/templates/subtemplate.html b/ambari-common/src/main/python/ambari_jinja2/ext/django2jinja/templates/subtemplate.html
new file mode 100644
index 0000000..980a0d5
--- /dev/null
+++ b/ambari-common/src/main/python/ambari_jinja2/ext/django2jinja/templates/subtemplate.html
@@ -0,0 +1 @@
+Hello World!

http://git-wip-us.apache.org/repos/asf/ambari/blob/7c3ea59f/ambari-common/src/main/python/ambari_jinja2/ext/djangojinja2.py
----------------------------------------------------------------------
diff --git a/ambari-common/src/main/python/ambari_jinja2/ext/djangojinja2.py b/ambari-common/src/main/python/ambari_jinja2/ext/djangojinja2.py
new file mode 100644
index 0000000..9032400
--- /dev/null
+++ b/ambari-common/src/main/python/ambari_jinja2/ext/djangojinja2.py
@@ -0,0 +1,86 @@
+# -*- coding: utf-8 -*-
+"""
+    djangoambari_jinja2
+    ~~~~~~~~~~~~
+
+    Adds support for Jinja2 to Django.
+
+    Configuration variables:
+
+    ======================= =============================================
+    Key                     Description
+    ======================= =============================================
+    `JINJA2_TEMPLATE_DIRS`  List of template folders
+    `JINJA2_EXTENSIONS`     List of Jinja2 extensions to use
+    `JINJA2_CACHE_SIZE`     The size of the Jinja2 template cache.
+    ======================= =============================================
+
+    :copyright: (c) 2009 by the Jinja Team.
+    :license: BSD.
+"""
+from itertools import chain
+from django.conf import settings
+from django.http import HttpResponse
+from django.core.exceptions import ImproperlyConfigured
+from django.template.context import get_standard_processors
+from django.template import TemplateDoesNotExist
+from ambari_jinja2 import Environment, FileSystemLoader, TemplateNotFound
+from ambari_jinja2.defaults import DEFAULT_NAMESPACE
+
+
+# the environment is unconfigured until the first template is loaded.
+_jinja_env = None
+
+
+def get_env():
+    """Get the Jinja2 env and initialize it if necessary."""
+    global _jinja_env
+    if _jinja_env is None:
+        _jinja_env = create_env()
+    return _jinja_env
+
+
+def create_env():
+    """Create a new Jinja2 environment."""
+    searchpath = list(settings.JINJA2_TEMPLATE_DIRS)
+    return Environment(loader=FileSystemLoader(searchpath),
+                       auto_reload=settings.TEMPLATE_DEBUG,
+                       cache_size=getattr(settings, 'JINJA2_CACHE_SIZE', 50),
+                       extensions=getattr(settings, 'JINJA2_EXTENSIONS', ()))
+
+
+def get_template(template_name, globals=None):
+    """Load a template."""
+    try:
+        return get_env().get_template(template_name, globals=globals)
+    except TemplateNotFound, e:
+        raise TemplateDoesNotExist(str(e))
+
+
+def select_template(templates, globals=None):
+    """Try to load one of the given templates."""
+    env = get_env()
+    for template in templates:
+        try:
+            return env.get_template(template, globals=globals)
+        except TemplateNotFound:
+            continue
+    raise TemplateDoesNotExist(', '.join(templates))
+
+
+def render_to_string(template_name, context=None, request=None,
+                     processors=None):
+    """Render a template into a string."""
+    context = dict(context or {})
+    if request is not None:
+        context['request'] = request
+        for processor in chain(get_standard_processors(), processors or ()):
+            context.update(processor(request))
+    return get_template(template_name).render(context)
+
+
+def render_to_response(template_name, context=None, request=None,
+                       processors=None, mimetype=None):
+    """Render a template into a response object."""
+    return HttpResponse(render_to_string(template_name, context, request,
+                                         processors), mimetype=mimetype)

http://git-wip-us.apache.org/repos/asf/ambari/blob/7c3ea59f/ambari-common/src/main/python/ambari_jinja2/ext/inlinegettext.py
----------------------------------------------------------------------
diff --git a/ambari-common/src/main/python/ambari_jinja2/ext/inlinegettext.py b/ambari-common/src/main/python/ambari_jinja2/ext/inlinegettext.py
new file mode 100644
index 0000000..ba585f3
--- /dev/null
+++ b/ambari-common/src/main/python/ambari_jinja2/ext/inlinegettext.py
@@ -0,0 +1,78 @@
+# -*- coding: utf-8 -*-
+"""
+    Inline Gettext
+    ~~~~~~~~~~~~~~
+
+    An example extension for Jinja2 that supports inline gettext calls.
+    Requires the i18n extension to be loaded.
+
+    :copyright: (c) 2009 by the Jinja Team.
+    :license: BSD.
+"""
+import re
+from ambari_jinja2.ext import Extension
+from ambari_jinja2.lexer import Token, count_newlines
+from ambari_jinja2.exceptions import TemplateSyntaxError
+
+
+_outside_re = re.compile(r'\\?(gettext|_)\(')
+_inside_re = re.compile(r'\\?[()]')
+
+
+class InlineGettext(Extension):
+    """This extension implements support for inline gettext blocks::
+
+        <h1>_(Welcome)</h1>
+        <p>_(This is a paragraph)</p>
+
+    Requires the i18n extension to be loaded and configured.
+    """
+
+    def filter_stream(self, stream):
+        paren_stack = 0
+
+        for token in stream:
+            if token.type is not 'data':
+                yield token
+                continue
+
+            pos = 0
+            lineno = token.lineno
+
+            while 1:
+                if not paren_stack:
+                    match = _outside_re.search(token.value, pos)
+                else:
+                    match = _inside_re.search(token.value, pos)
+                if match is None:
+                    break
+                new_pos = match.start()
+                if new_pos > pos:
+                    preval = token.value[pos:new_pos]
+                    yield Token(lineno, 'data', preval)
+                    lineno += count_newlines(preval)
+                gtok = match.group()
+                if gtok[0] == '\\':
+                    yield Token(lineno, 'data', gtok[1:])
+                elif not paren_stack:
+                    yield Token(lineno, 'block_begin', None)
+                    yield Token(lineno, 'name', 'trans')
+                    yield Token(lineno, 'block_end', None)
+                    paren_stack = 1
+                else:
+                    if gtok == '(' or paren_stack > 1:
+                        yield Token(lineno, 'data', gtok)
+                    paren_stack += gtok == ')' and -1 or 1
+                    if not paren_stack:
+                        yield Token(lineno, 'block_begin', None)
+                        yield Token(lineno, 'name', 'endtrans')
+                        yield Token(lineno, 'block_end', None)
+                pos = match.end()
+
+            if pos < len(token.value):
+                yield Token(lineno, 'data', token.value[pos:])
+
+        if paren_stack:
+            raise TemplateSyntaxError('unclosed gettext expression',
+                                      token.lineno, stream.name,
+                                      stream.filename)